ztttttt 2 weeks ago
parent
commit
76185b262b
11 changed files with 217 additions and 39 deletions
  1. 1 1
      .idea/PythonProject.iml
  2. 49 0
      .idea/deployment.xml
  3. 1 1
      .idea/misc.xml
  4. 1 1
      .idea/vcs.xml
  5. BIN
      __pycache__/bit_api.cpython-38.pyc
  6. BIN
      __pycache__/utils.cpython-38.pyc
  7. 1 1
      allcode.py
  8. 79 33
      allcode_by.py
  9. 2 2
      config.json
  10. 20 0
      post.py
  11. 63 0
      test.py

+ 1 - 1
.idea/PythonProject.iml

@@ -2,7 +2,7 @@
 <module type="PYTHON_MODULE" version="4">
   <component name="NewModuleRootManager">
     <content url="file://$MODULE_DIR$" />
-    <orderEntry type="jdk" jdkName="django" jdkType="Python SDK" />
+    <orderEntry type="jdk" jdkName="rpc" jdkType="Python SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
 </module>

+ 49 - 0
.idea/deployment.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
+    <serverData>
+      <paths name="root@connect.nmb1.seetacloud.com:31276 password">
+        <serverdata>
+          <mappings>
+            <mapping local="$PROJECT_DIR$" web="/" />
+          </mappings>
+        </serverdata>
+      </paths>
+      <paths name="root@connect.nmb1.seetacloud.com:42808 password">
+        <serverdata>
+          <mappings>
+            <mapping local="$PROJECT_DIR$" web="/" />
+          </mappings>
+        </serverdata>
+      </paths>
+      <paths name="root@connect.yza1.seetacloud.com:41276 password">
+        <serverdata>
+          <mappings>
+            <mapping local="$PROJECT_DIR$" web="/" />
+          </mappings>
+        </serverdata>
+      </paths>
+      <paths name="root@connect.yza1.seetacloud.com:41276 password (2)">
+        <serverdata>
+          <mappings>
+            <mapping local="$PROJECT_DIR$" web="/" />
+          </mappings>
+        </serverdata>
+      </paths>
+      <paths name="root@connect.yza1.seetacloud.com:41276 password (3)">
+        <serverdata>
+          <mappings>
+            <mapping local="$PROJECT_DIR$" web="/" />
+          </mappings>
+        </serverdata>
+      </paths>
+      <paths name="root@connect.yza1.seetacloud.com:41276 password (4)">
+        <serverdata>
+          <mappings>
+            <mapping local="$PROJECT_DIR$" web="/" />
+          </mappings>
+        </serverdata>
+      </paths>
+    </serverData>
+  </component>
+</project>

+ 1 - 1
.idea/misc.xml

@@ -3,5 +3,5 @@
   <component name="Black">
     <option name="sdkName" value="django" />
   </component>
-  <component name="ProjectRootManager" version="2" project-jdk-name="django" project-jdk-type="Python SDK" />
+  <component name="ProjectRootManager" version="2" project-jdk-name="rpc" project-jdk-type="Python SDK" />
 </project>

+ 1 - 1
.idea/vcs.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="VcsDirectoryMappings">
-    <mapping directory="$PROJECT_DIR$/auto_ui" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
   </component>
 </project>

BIN
__pycache__/bit_api.cpython-38.pyc


BIN
__pycache__/utils.cpython-38.pyc


+ 1 - 1
allcode.py

@@ -72,7 +72,6 @@ def start_Ads_data(PROFILE_ID, data:list):
     time.sleep(1)
     # 选择州
 
-
     Select(web.find_element(By.XPATH, "(.//*[normalize-space(text()) and normalize-space(.)='*'])[5]/preceding::select[1]")).select_by_index(abbreviation_to_index[data[4]])
     # 选择code
     web.find_element(By.ID, "zip").send_keys(data[5])
@@ -83,6 +82,7 @@ def start_Ads_data(PROFILE_ID, data:list):
     # 确认
     web.find_element(By.XPATH, "//input[@type='checkbox']").click()
     # 金额
+    "//input[@value='$1-$500']"
     web.find_element(By.XPATH, "//input[@value='$501-$1,000']").click()
     # 签名
     web.find_element(By.ID, "signature").send_keys(data[1])

+ 79 - 33
allcode_by.py

@@ -1,4 +1,3 @@
-import requests
 import time
 import tkinter as tk
 from tkinter import ttk, filedialog, messagebox
@@ -21,6 +20,7 @@ from multiprocessing import Process
 logging.basicConfig(level=logging.INFO)
 logger = logging.getLogger(__name__)
 
+
 # 自定义日志处理器,用于将日志输出到 GUI 的文本框
 class TextHandler(logging.Handler):
     def __init__(self, text_widget, adjust_height_callback):
@@ -34,6 +34,7 @@ class TextHandler(logging.Handler):
         self.text_widget.see(tk.END)
         self.adjust_height_callback()
 
+
 # GUI 类
 class AdsDataGUI:
     def __init__(self, root):
@@ -50,13 +51,13 @@ class AdsDataGUI:
 
         # 参数输入框
         self.params = {
-            "WINDOW_ID": tk.StringVar(value=self.config.get("WINDOW_ID", "947c8036facb4e8a935296e57f36652b")),
+            "WINDOW_ID": tk.StringVar(value=self.config.get("WINDOW_ID", "5c2216ed3b3e4bf0bc144b5ad0c87a5b")),
             "BASE_URL": tk.StringVar(value=self.config.get("BASE_URL", "http://127.0.0.1:54345")),
             "API_KEY": tk.StringVar(value=self.config.get("API_KEY", "704daf420f7244d08be51f61c987a232")),
             "FILE_PATH": tk.StringVar(value=self.config.get("FILE_PATH", "generated_data.txt")),
             "AMOUNT": tk.StringVar(value=self.config.get("AMOUNT", "$501-$1,000")),
             "SLEEP_TIME_1": tk.DoubleVar(value=self.config.get("SLEEP_TIME_1", 10.0)),  # 验证码等待时间
-            "SLEEP_TIME_2": tk.DoubleVar(value=self.config.get("SLEEP_TIME_2", 3.0)),   # 提交后等待时间
+            "SLEEP_TIME_2": tk.DoubleVar(value=self.config.get("SLEEP_TIME_2", 3.0)),  # 提交后等待时间
             "SLEEP_TIME_3": tk.DoubleVar(value=self.config.get("SLEEP_TIME_3", 10.0)),  # 关闭后等待时间
             "NO_SANDBOX": tk.BooleanVar(value=self.config.get("NO_SANDBOX", True)),
             "DISABLE_DEV_SHM": tk.BooleanVar(value=self.config.get("DISABLE_DEV_SHM", True)),
@@ -85,7 +86,8 @@ class AdsDataGUI:
 
         # 创建 GUI 元素(中文界面)
         row = 0
-        tk.Label(self.scrollable_frame, text="自动化注册 - BitBrowser", font=("Arial", 16)).grid(row=row, column=0, columnspan=3, pady=10)
+        tk.Label(self.scrollable_frame, text="自动化注册 - BitBrowser", font=("Arial", 16)).grid(row=row, column=0,
+                                                                                                 columnspan=3, pady=10)
         row += 1
 
         # 参数输入框
@@ -103,19 +105,26 @@ class AdsDataGUI:
         for label_text, var in labels:
             tk.Label(self.scrollable_frame, text=label_text).grid(row=row, column=0, sticky="e", padx=5, pady=5)
             if label_text == "金额范围:":
-                amount_options = ["$0-$500", "$501-$1,000", "$1,001-$5,000", "超过 $5,000"]
-                ttk.Combobox(self.scrollable_frame, textvariable=var, values=amount_options, state="readonly").grid(row=row, column=1, padx=5, pady=5, sticky="ew")
+                amount_options = ["$1-$500", "$501-$1,000", "$1,001-$5,000", "超过 $5,000"]
+                ttk.Combobox(self.scrollable_frame, textvariable=var, values=amount_options, state="readonly").grid(
+                    row=row, column=1, padx=5, pady=5, sticky="ew")
             else:
                 tk.Entry(self.scrollable_frame, textvariable=var).grid(row=row, column=1, padx=5, pady=5, sticky="ew")
             if label_text == "文件路径:":
-                tk.Button(self.scrollable_frame, text="浏览", command=self.browse_file).grid(row=row, column=2, padx=5, pady=5)
+                tk.Button(self.scrollable_frame, text="浏览", command=self.browse_file).grid(row=row, column=2, padx=5,
+                                                                                             pady=5)
             row += 1
 
-        tk.Checkbutton(self.scrollable_frame, text="无沙盒模式", variable=self.params["NO_SANDBOX"]).grid(row=row, column=0, columnspan=3, pady=5)
+        tk.Checkbutton(self.scrollable_frame, text="无沙盒模式", variable=self.params["NO_SANDBOX"]).grid(row=row,
+                                                                                                          column=0,
+                                                                                                          columnspan=3,
+                                                                                                          pady=5)
         row += 1
-        tk.Checkbutton(self.scrollable_frame, text="禁用 Dev SHM", variable=self.params["DISABLE_DEV_SHM"]).grid(row=row, column=0, columnspan=3, pady=5)
+        tk.Checkbutton(self.scrollable_frame, text="禁用 Dev SHM", variable=self.params["DISABLE_DEV_SHM"]).grid(
+            row=row, column=0, columnspan=3, pady=5)
         row += 1
-        tk.Checkbutton(self.scrollable_frame, text="启动时最大化", variable=self.params["START_MAXIMIZED"]).grid(row=row, column=0, columnspan=3, pady=5)
+        tk.Checkbutton(self.scrollable_frame, text="启动时最大化", variable=self.params["START_MAXIMIZED"]).grid(
+            row=row, column=0, columnspan=3, pady=5)
         row += 1
 
         self.status_label = tk.Label(self.scrollable_frame, text="状态: 就绪", fg="blue")
@@ -262,7 +271,7 @@ class AdsDataGUI:
                         logger.info("用户停止了脚本")
                         break
                     try:
-                        start_Ads_data(
+                        result = start_Ads_data(
                             self,
                             data,
                             window_id=self.params["WINDOW_ID"].get(),
@@ -278,7 +287,14 @@ class AdsDataGUI:
                             },
                             amount=self.params["AMOUNT"].get()
                         )
-                        break  # 成功则跳出重试循环
+                        if result:
+                            logger.info("操作成功!")
+                            break  # 成功则跳出循环
+                        else:
+                            # 返回 False 时触发重试
+                            logger.warning(f"尝试 {attempt + 1} 失败(业务逻辑错误),等待 10 秒后重试...")
+                            time.sleep(10)
+
                     except Exception as e:
                         if not self.running:
                             logger.info("用户停止了脚本")
@@ -298,52 +314,54 @@ class AdsDataGUI:
             self.running = False
             self.current_web = None
 
+
 def start_Ads_data(gui, data, window_id, sleep_times, chrome_options, amount):
+
     # 使用 BitBrowser 窗口 ID
     res = openBrowser(window_id)
-    
+
     # 调试:打印 openBrowser 的返回值
     logger.info(f"openBrowser Response: {res}")
-    
+
     # 检查返回值是否包含 'data' 键
     if 'data' not in res:
         logger.error("BitBrowser API 返回中没有 'data' 键")
         raise Exception("BitBrowser API 返回中没有 'data' 键")
-    
+
     driverPath = res['data']['driver']
     debuggerAddress = res['data']['http']
-    
+
     if res["success"] is True:
         logger.info("启动成功,返回信息")
     else:
         logger.error("启动失败")
         raise Exception("启动失败")
-    
+
     chrome_opts = webdriver.ChromeOptions()
     chrome_opts.add_experimental_option("debuggerAddress", debuggerAddress)
-    
+
     if chrome_options["no_sandbox"]:
         chrome_opts.add_argument('--no-sandbox')
     if chrome_options["disable_dev_shm"]:
         chrome_opts.add_argument('--disable-dev-shm-usage')
     if chrome_options["start_maximized"]:
         chrome_opts.add_argument('--start-maximized')
-    
+
     chrome_service = Service(driverPath)
     web = webdriver.Chrome(service=chrome_service, options=chrome_opts)
     web.implicitly_wait(30)
-    
+
     # 将 web 实例保存到 GUI 对象,以便在停止时关闭
     gui.current_web = web
-    
+
     web.get("https://claimform.savingsclubsettlement.com/consumerb-claimants")
-    
+
     original_window = web.current_window_handle
     logger.info(f"当前页面标题: {web.title}")
-    
+
     time.sleep(sleep_times["sleep1"])
     logger.info("等待验证码识别")
-    
+
     try:
         iframe = WebDriverWait(web, 10).until(
             EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[src*='google.com/recaptcha']"))
@@ -351,7 +369,7 @@ def start_Ads_data(gui, data, window_id, sleep_times, chrome_options, amount):
     except TimeoutException:
         logger.error("未找到reCAPTCHA iframe")
         raise Exception("未找到reCAPTCHA iframe")
-    
+
     while True:
         try:
             WebDriverWait(web, 10).until(
@@ -363,37 +381,64 @@ def start_Ads_data(gui, data, window_id, sleep_times, chrome_options, amount):
             logger.warning("验证未完成或失败")
         finally:
             web.switch_to.default_content()
-    
+
     web.switch_to.default_content()
     web.find_element(By.XPATH, "//input[@type='text']").send_keys(data[1])
     web.find_element(By.ID, "street1").send_keys(data[2])
     web.find_element(By.ID, "city").send_keys(data[3])
     time.sleep(1)
-    Select(web.find_element(By.XPATH, "(.//*[normalize-space(text()) and normalize-space(.)='*'])[5]/preceding::select[1]")).select_by_index(abbreviation_to_index[data[4]])
+    Select(web.find_element(By.XPATH,
+                            "(.//*[normalize-space(text()) and normalize-space(.)='*'])[5]/preceding::select[1]")).select_by_index(
+        abbreviation_to_index[data[4]])
     web.find_element(By.ID, "zip").send_keys(data[5])
     time.sleep(1)
     web.find_element(By.ID, "email").send_keys(data[0])
     web.find_element(By.XPATH, "//input[@type='checkbox']").click()
+
     web.find_element(By.XPATH, f"//input[@value='{amount}']").click()
     web.find_element(By.ID, "signature").send_keys(data[1])
-    
+
     submit_button = WebDriverWait(web, 10).until(EC.element_to_be_clickable((By.XPATH, "//button[@type='submit']")))
     submit_button.click()
+    # 验证提取是否成功
+    result = check_submission_success(data, web)
+
     time.sleep(sleep_times["sleep2"])
     web.delete_all_cookies()
     web.execute_script("window.localStorage.clear();")
     web.execute_script("window.sessionStorage.clear();")
     web.quit()
     time.sleep(sleep_times["sleep3"])
-    
+
     # 使用 BitBrowser 窗口 ID
     closeBrowser(window_id)
-    
+
     # 添加延迟,确保窗口完全关闭
     logger.info("等待窗口完全关闭...")
     time.sleep(sleep_times["sleep3"])
-    
-    logger.info("完成一次")
+
+    logger.info("完成一次填表循环")
+
+    return result
+
+
+def check_submission_success(data, web):
+    try:
+        # 等待成功标题出现(显式等待)
+        WebDriverWait(web, 15).until(
+            EC.visibility_of_element_located((By.XPATH, "//h2[contains(., 'THANK YOU FOR SUBMITTING')]"))
+        )
+        # 获取参考号和日期
+        ref_number = web.find_element(By.XPATH, "//p[contains(., 'Your Reference Number is')]/b").text
+        submission_date = web.find_element(By.XPATH, "//p[contains(., 'submitted on')]/b").text
+
+        logger.info(", ".join(data) + "提交成功" + ref_number)
+        return True
+
+    except Exception as e:
+        print(", ".join(data)+"")
+        return False
+
 
 def read_txt_file(file_path):
     data = []
@@ -416,7 +461,8 @@ def read_txt_file(file_path):
         return None
     return data
 
+
 if __name__ == '__main__':
     root = tk.Tk()
     app = AdsDataGUI(root)
-    root.mainloop()
+    root.mainloop()

+ 2 - 2
config.json

@@ -1,9 +1,9 @@
 {
-    "WINDOW_ID": "947c8036facb4e8a935296e57f36652b",
+    "WINDOW_ID": "5c2216ed3b3e4bf0bc144b5ad0c87a5b",
     "BASE_URL": "http://127.0.0.1:54345",
     "API_KEY": "704daf420f7244d08be51f61c987a232",
     "FILE_PATH": "generated_data.txt",
-    "AMOUNT": "$501-$1,000",
+    "AMOUNT": "$1-$500",
     "SLEEP_TIME_1": 10.0,
     "SLEEP_TIME_2": 3.0,
     "SLEEP_TIME_3": 10.0,

+ 20 - 0
post.py

@@ -0,0 +1,20 @@
+# 安装最新库
+# pip install --upgrade nopecha
+
+import nopecha
+
+# 配置API密钥和代理(按需)
+nopecha.api_key = 'sub_1R40KKCRwBwvt6ptesU6SVpK'
+nopecha.proxy = None  # 确保无代理干扰
+
+try:
+    # 调用API(假设实际使用 hCaptcha)
+    clicks = nopecha.Recognition.solve(
+        type='hcaptcha',
+        task='Click all vehicles',
+        image_urls=['https://nopecha.com/image/demo/hcaptcha/4x4.png'],
+        grid='4x4'
+    )
+    print("需点击的网格坐标:", clicks)
+except nopecha.error.APIError as e:
+    print("错误详情:", e.json().get('error', '未知错误'))

+ 63 - 0
test.py

@@ -0,0 +1,63 @@
+import time
+import tkinter as tk
+from tkinter import ttk, filedialog, messagebox
+import json
+import os
+import threading
+import logging
+from selenium import webdriver
+from selenium.webdriver.common.by import By
+from selenium.webdriver.chrome.service import Service
+from selenium.webdriver.support.ui import Select
+from selenium.webdriver.support import expected_conditions as EC
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.common.exceptions import TimeoutException
+from utils import abbreviation_to_index
+from bit_api import *
+from multiprocessing import Process
+
+res = openBrowser('5c2216ed3b3e4bf0bc144b5ad0c87a5b')
+
+
+# 检查返回值是否包含 'data' 键
+if 'data' not in res:
+    print("BitBrowser API 返回中没有 'data' 键")
+    raise Exception("BitBrowser API 返回中没有 'data' 键")
+
+driverPath = res['data']['driver']
+debuggerAddress = res['data']['http']
+
+if res["success"] is True:
+    print("启动成功,返回信息")
+else:
+    print("启动失败")
+    raise Exception("启动失败")
+
+chrome_opts = webdriver.ChromeOptions()
+chrome_opts.add_experimental_option("debuggerAddress", debuggerAddress)
+
+
+
+chrome_service = Service(driverPath)
+web = webdriver.Chrome(service=chrome_service, options=chrome_opts)
+web.implicitly_wait(30)
+
+web.get("https://www.google.com/recaptcha/api2/demo")
+
+WebDriverWait(web, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, "//iframe[contains(@title, 'reCAPTCHA')]")))
+recaptcha_anchor = WebDriverWait(web, 10).until(
+    EC.element_to_be_clickable((By.XPATH, "//span[@id='recaptcha-anchor']/div"))
+)
+recaptcha_anchor.click()
+web.switch_to.default_content()
+
+WebDriverWait(web, 5).until(
+                EC.frame_to_be_available_and_switch_to_it(
+                    (By.XPATH, "//iframe[contains(@title, 'recaptcha challenge')]"))
+            )
+
+element = WebDriverWait(web, 10).until(
+        EC.presence_of_element_located((By.XPATH, '//div[contains(@class, "rc-imageselect")]//div'))
+    ).text
+
+print(element)