jerry 3 tygodni temu
rodzic
commit
5b92ff4555
4 zmienionych plików z 376 dodań i 132 usunięć
  1. 373 129
      tls_registration_bot.py
  2. 1 1
      utils/cloudflare_bypass_for_scraping.py
  3. 1 1
      utils/mouse.py
  4. 1 1
      utils/scroll.py

+ 373 - 129
tls_registration_bot.py

@@ -5,21 +5,33 @@ import re
 import uuid
 import socket
 import shutil
+import random
 import requests
+from urllib.parse import urlencode
 from datetime import datetime, timedelta
+from typing import Optional, Dict
+from DrissionPage.common import Keys
 from DrissionPage import ChromiumPage, ChromiumOptions
 from utils.cloudflare_bypass_for_scraping import CloudflareBypasser
 from toolkit.vs_cloud_api import VSCloudApi
+from vs_types import NotFoundError, PermissionDeniedError, RateLimiteddError, SessionExpiredOrInvalidError, BizLogicError 
+from utils.mouse import HumanMouse
+from utils.keyboard import HumanKeyboard
+from utils.scroll import HumanScroll
 
 class TlsRegistrator:
-    def __init__(self, proxy_config: dict, capsolver_key: str):
+    def __init__(self, tls_url, proxy_config: Optional[Dict]=None, capsolver_key: Optional[str]=None, account_detail: Optional[Dict]=None):
         self.proxy_config = proxy_config
         self.capsolver_key = capsolver_key
-        
+        self.account_detail = account_detail
         # 隔离的用户数据目录
-        self.instance_id = uuid.uuid4().hex[:8]
+        #self.instance_id = uuid.uuid4().hex[:8]
+        self.tls_url = tls_url
+        self.instance_id = '18d389e9'
         self.workspace = os.path.abspath(os.path.join("data", f"reg_session_{self.instance_id}"))
         self.page = None
+        self.mouse = None
+        self.keyboard = None
 
     def _log(self, msg):
         print(f"[TLS-Reg-{self.instance_id}] {msg}")
@@ -53,145 +65,146 @@ class TlsRegistrator:
 
         # 3. 反爬及稳定性配置
         co.headless(False)
+        co.set_argument('--lang=en-US')
         co.set_argument('--no-sandbox')
         co.set_argument('--disable-gpu')
         co.set_argument('--disable-dev-shm-usage')
         co.set_argument('--window-size=1920,1080')
         co.set_argument('--disable-blink-features=AutomationControlled')
-
         self.page = ChromiumPage(co)
-
-    def solve_captcha(self, page_url: str, site_key: str) -> str:
-        """调用 Capsolver 解决验证码 (无依赖版本)"""
-        if not self.capsolver_key:
-            raise ValueError("Capsolver API key is missing!")
-            
-        self._log("Submitting captcha task to Capsolver...")
+        self.page.run_cdp('Emulation.setLocaleOverride', locale='en-US')
+        self.page.get(self.tls_url)
+        cf_bypasser = CloudflareBypasser(self.page, log=True)
+        cf_bypasser.bypass()
+        time.sleep(3) 
+        cf_bypasser.handle_waiting_room()
         
+        self._log("正在初始化拟人化工具...")
+        self.mouse = HumanMouse(self.page, debug=True)
+        self.keyboard = HumanKeyboard(self.page)
+        self._log("随机化鼠标开始位置...")
+        viewport_width = self.page.rect.viewport_size[0]
+        viewport_height = self.page.rect.viewport_size[1]
+        init_x = random.randint(10, viewport_width - 10)
+        init_y = random.randint(10, viewport_height - 10)
+        self.mouse.move(init_x, init_y) 
+        
+    def solve_captcha(self, page_url: str, task_type: str, site_key: str, use_proxy = False, action: str = None, api_domain: str = None) -> str:
+        """通用解决验证码 (同步 User-Agent 防止被盾识别为高风险)"""
+        if not self.capsolver_key:
+            raise ValueError("Capsolver API key missing")
+
         task = {
-            "type": "ReCaptchaV3TaskProxyLess", 
+            "type": task_type,
             "websiteURL": page_url,
             "websiteKey": site_key,
-            "pageAction": "register"
         }
         
-        payload = {
-            "clientKey": self.capsolver_key, 
-            "task": task
-        }
-        print(f'createTask payload={payload}')
-        create_res = requests.post("https://api.capsolver.com/createTask", json=payload, timeout=20)
-        if create_res.status_code != 200 or create_res.json().get("errorId") != 0:
-            raise Exception(f"Failed to create capsolver task: {create_res.text}")
+        if api_domain:
+            task["apiDomain"] = api_domain
             
-        task_id = create_res.json().get("taskId")
-        self._log(f"Captcha Task created: {task_id}. Waiting for solution...")
-        
+        if use_proxy:
+            proxy = self.proxy_config
+            task["proxyType"] = proxy.get('scheme', 'http')
+            task["proxyAddress"] = proxy.get('ip')
+            task["proxyPort"] = int(proxy.get('port'))
+            if proxy.get('username'):
+                task["proxyLogin"] = proxy.get('username')
+                task["proxyPassword"] = proxy.get('password')
+                
+        if action:
+            task["pageAction"] = action
+
+        payload = {"clientKey": self.capsolver_key, "task": task}
+        res = requests.post("https://api.capsolver.com/createTask", json=payload, timeout=20)
+        if res.status_code != 200 or res.json().get("errorId") != 0:
+            raise Exception(f"Failed to create capsolver task: {res.text}")
+
+        task_id = res.json().get("taskId")
+        self._log(f"Task created: {task_id}. Waiting for solution...")
+
         for _ in range(30):
-            res = requests.post(
+            r = requests.post(
                 "https://api.capsolver.com/getTaskResult", 
                 json={"clientKey": self.capsolver_key, "taskId": task_id}, 
                 timeout=20
             )
-            data = res.json()
-            self._log(f"data={data}")
+            data = r.json()
             if data.get("status") == "ready":
                 self._log("Captcha solved successfully!")
-                return data.get("solution", {}).get("gRecaptchaResponse") or data.get("solution", {}).get("token")
+                return data["solution"].get("gRecaptchaResponse") or data["solution"].get("token")
             time.sleep(3)
-            
         raise Exception("Capsolver task timeout")
 
-    def register(self, email, password, issuer_id="cnCNG2fr"):
+    def register(self):
         """执行自动注册"""
-        try:
-            self.init_browser()
-            
-            # 1. 访问注册页面并过盾
-            reg_url = f"https://visas-fr.tlscontact.com/en-us/registration?issuerId={issuer_id}"
-            self._log(f"Navigating to {reg_url}")
-            self.page.get(reg_url)
-            cf_bypasser = CloudflareBypasser(self.page, log=True)
-            cf_bypasser.bypass()
-            time.sleep(3) 
-            
-            cf_bypasser.handle_waiting_room()
+        email = self.account_detail.get('email')
+        password = self.account_detail.get('pwd')
+        btn_selector = '#submit'
+        if not self.page.wait.ele_displayed(btn_selector, timeout=3):
+            register_btn = self.page.ele("tag:a@@href:registration")
+            self.mouse.move_to(register_btn)
+            self.mouse.click(register_btn.rect.midpoint[0], register_btn.rect.midpoint[1], humanize=True)
+            time.sleep(3)
+        if not self.page.wait.ele_displayed(btn_selector, timeout=10):
+            raise BizLogicError(message=f"Can't find selector={btn_selector}")
+        time.sleep(random.uniform(0.5, 1))
+        self._log("正在填写邮箱和密码...")
+        email_input_e = self.page.ele('#email')
+        self.mouse.click(int(email_input_e.rect.midpoint[0]), int(email_input_e.rect.midpoint[1]), humanize=True)
+        self.keyboard.type_text(email, humanize=True)
+        time.sleep(random.uniform(0.2, 0.5))
+        
+        password_e = self.page.ele('#password')
+        self.mouse.click(int(password_e.rect.midpoint[0]), int(password_e.rect.midpoint[1]), humanize=True)
+        self.keyboard.type_text(password, humanize=True)
+        time.sleep(random.uniform(0.2, 0.5))
+        
+        confirm_password_e = self.page.ele('#confirm-password')
+        self.mouse.click(int(confirm_password_e.rect.midpoint[0]), int(confirm_password_e.rect.midpoint[1]), humanize=True)
+        self.keyboard.type_text(password, humanize=True)
+        time.sleep(random.uniform(0.2, 0.5))
 
-            site_key = "6LcTpXcfAAAAAM3VojNhyV-F1z92ADJIvcSZ39Y9" 
-            captcha_token = self.solve_captcha(reg_url, site_key)
+        self._log("正在勾选必选条款...")
+        for checkbox_id in ['#terms-and-conditions', '#biometric-data', '#privacy-notice']:
+            check_box_e = self.page.ele(checkbox_id).next()
+            mx, my = int(check_box_e.rect.midpoint[0]), int(check_box_e.rect.midpoint[1])
+            self.mouse.click(mx, my, humanize=True)
+            time.sleep(random.uniform(0.3, 0.6))
+                
+        self._log("提交注册...")
+        btn_e = self.page.ele(btn_selector)
+        
+        btn_e.scroll.to_see(center=True) 
+        time.sleep(1)
+        
+        btn_mx, btn_my = int(btn_e.rect.midpoint[0]), int(btn_e.rect.midpoint[1])
+        self.mouse.click(btn_mx, btn_my, humanize=True)
+        
+        time.sleep(0.5)
+        btn_e.click(by_js=True)
 
-            self._log("Constructing Next.js fetch request...")
-            action_id = "608511a5a6e58da30dc13b591255b358caa2193367"
-            router_state = '%5B%22%22%2C%7B%22children%22%3A%5B%5B%22lang%22%2C%22en-us%22%2C%22d%22%5D%2C%7B%22children%22%3A%5B%22(auth)%22%2C%7B%22children%22%3A%5B%22registration%22%2C%7B%22children%22%3A%5B%22__PAGE__%22%2C%7B%7D%2Cnull%2Cnull%5D%7D%2Cnull%2Cnull%5D%7D%2Cnull%2Cnull%5D%7D%2Cnull%2Cnull%2Ctrue%5D%7D%2Cnull%2Cnull%5D'
-            
-            payload =[
-                {
-                    "email": email,
-                    "password": password,
-                    "locale": "en",
-                    "issuerId": issuer_id,
-                    "consentList": ["SURVEY"]
-                },
-                captcha_token
-            ]
-            
-            body_str = json.dumps(payload).replace("'", "\\'")
-
-            js_script = f"""
-            const url = "{reg_url}";
-            const headers = {{
-                'next-action': '{action_id}',
-                'next-router-state-tree': '{router_state}',
-                'accept': 'text/x-component',
-                'content-type': 'text/plain;charset=UTF-8'
-            }};
-            const bodyData = '{body_str}';
-            
-            return fetch(url, {{ method: 'POST', headers: headers, body: bodyData }})
-                .then(async response => {{
-                    const text = await response.text();
-                    const headers = {{}};
-                    response.headers.forEach((value, key) => headers[key] = value);
-                    return {{ status: response.status, body: text, headers: headers, url: response.url }};
-                }}).catch(err => {{
-                    return {{ status: 0, body: err.toString(), headers: {{}} }};
-                }});
-            """
-
-            self._log("Submitting registration...")
-            res_dict = self.page.run_js(js_script)
-            
-            # 4. 解析结果 (处理 Next.js Server Action 响应)
-            status = res_dict.get('status')
-            body_text = res_dict.get('body', '')
-            resp_headers = {str(k).lower(): v for k, v in res_dict.get('headers', {}).items()}
-            action_redirect = resp_headers.get('x-action-redirect', '')
-            
-            # 【核心修改点】:适配 Next.js 响应中的 "status":"OK"
-            is_success = (
-                status == 303 or 
-                (status == 200 and ("login" in action_redirect or '"status":"OK"' in body_text))
-            )
+        self._log("正在等待验证结果 (最多10秒)...")
+        success_dialog = self.page.wait.ele_displayed('tag:h1@text():Check your email inbox', timeout=10)
 
-            if is_success:
-                self._log("✅ Registration SUCCESS!")
-                self._log(f"Response snippet: {body_text[:100]}...")
-                return True
-            else:
-                self._log(f"❌ Registration FAILED! Status: {status}")
-                self._log(f"Response Body: {body_text[:500]}")
-                return False
-        except Exception as e:
-            self._log(f"Error during registration: {e}")
-            return False
+        if not success_dialog:
+            self.page.get_screenshot("failed_submit.png") 
+            raise BizLogicError(message='Failed to submit account registration')     
+        self._log("✅ 操作成功!已弹出提示:Check your email inbox")
+        return True
     
-    def activate(self, email, sent_at=None):
+    def activate(self, sent_at=None):
+        email = self.account_detail.get('email')
         email_box = 'visafly666@gmail.com'
         sender = 'TLSContact'
         recipient = email
-        subject_keywords = 'Activate'
+        subject_keywords = 'TLSContact'
         body_keywords = ''
         
+        if not sent_at:
+            now_utc = datetime.utcnow()
+            sent_at = now_utc.strftime("%Y-%m-%d %H:%M:%S")
+        
         content_out = VSCloudApi.Instance().fetch_mail_content(
             email=email_box,
             sender=sender,
@@ -201,15 +214,227 @@ class TlsRegistrator:
             sent_date=sent_at,
             expiry=600
         )
-        print(f'activate email content={content_out}')
+        self._log(f'activate email content={content_out}')
         match = re.search(r'https://\S+', content_out)
         activate_link = match.group(0) if match else None
-        tab = self.page.new_tab(activate_link)
-        btn_selector = "Activate"
-        if not tab.wait.ele_displayed(btn_selector, timeout=10):
-            return False
-        tab.ele(btn_selector).click()
+        self.page.get(activate_link)
+        btn_selector = "#activation-pending-button"
+        if not self.page.wait.ele_displayed(btn_selector, timeout=10):
+            raise BizLogicError(message=f"Wait ele={btn_selector} timeout")
+        self.page.ele(btn_selector).click()
+        btn_selector = '#btn-login'
+        if not self.page.wait.ele_displayed(btn_selector, timeout=10):
+            raise BizLogicError(message=f"Wait ele={btn_selector} timeout")
+    
+    def make_account_useful(self):
+        
+        def fill_date_field(page, selector, date_str):
+            if not date_str:
+                return
+            ele = page.ele(selector)
+            ele.scroll.to_see(center=True)  # 滚动到屏幕中间
+            ele.click()
+            time.sleep(0.2)
+            year, month, day = date_str.split('-')
+            page.actions.type(year)
+            page.actions.type(Keys.TAB)
+            time.sleep(0.1)
+            page.actions.type(month)
+            time.sleep(0.1)
+            page.actions.type(day)
+        
+        email = self.account_detail.get('email')
+        password = self.account_detail.get('pwd')
+        location = self.account_detail.get('location')
+        btn_selector = '#btn-login'
+        if not self.page.wait.ele_displayed(btn_selector, timeout=3):
+            login_btn = self.page.ele("tag:a@@href:login")
+            self.mouse.move_to(login_btn)
+            self.mouse.click(login_btn.rect.midpoint[0], login_btn.rect.midpoint[1], humanize=True)
+            time.sleep(3)
+        if not self.page.wait.ele_displayed(btn_selector, timeout=10):
+            raise BizLogicError(message=f"Can't find selector={btn_selector}")
+        g_token = ""
+        if self.page.ele('.g-recaptcha') or self.page.ele('xpath://iframe[contains(@src, "recaptcha")]'):
+            self._log("Solving ReCaptcha...")
+            g_token = self.solve_captcha(self.page.url, "ReCaptchaV2TaskProxyLess", "6LcDpXcfAAAAAM7wOEsF_38DNsL20tTvPTKxpyn0")
+        
+        js_login = f"""
+        var u = document.getElementById('email-input-field');
+        if(u) {{ u.value = "{email}"; u.dispatchEvent(new Event('input', {{bubbles:true}})); }}
+        
+        var p = document.getElementById('password-input-field');
+        if(p) {{ p.value = "{password}"; p.dispatchEvent(new Event('input', {{bubbles:true}})); }}
+        
+        var g = document.getElementById('g-recaptcha-response');
+        if(g) {{ g.value = "{g_token}"; }}
+        
+        var btn = document.getElementById('btn-login');
+        if(btn) {{ btn.click(); return true; }} else {{ return false; }}
+        """
+        
+        self._log("Submitting Login via JS...")
+        if not self.page.run_js(js_login):
+            raise BizLogicError(message="Login button missing")
+
+        self._log("Waiting for dashboard redirect...")
+        self.page.wait.url_change('login-actions', exclude=True, timeout=45)
+        time.sleep(4)
+
+        if "login-actions" in self.page.url or "auth" in self.page.url:
+            raise BizLogicError(message="Login Failed! Invalid credentials or Captcha rejected.")
+
+        self._log("Waiting for dashboard...")
+        self.page.wait.load_start()
+        time.sleep(5)
+
+        # 解析 Dashboard 提取 Group ID
+        self._log("Parsing Dashboard for Travel Group...")
+        html = self.page.html
+        js_pattern = r'\\"travelGroups\\":\s*(\[.*?\]),\\"availableCountriesToCreateGroups'
+        js_match = re.search(js_pattern, html, re.DOTALL)
+        
+        groups = []
+        if js_match:
+            json_str = js_match.group(1).replace(r'\"', '"')
+            groups = json.loads(json_str)
+
+        travel_group = None
+        for g in groups:
+            if g.get('vacName', '').lower() == location.lower():
+                travel_group = g
+                break
+        
+        if not travel_group:
+            raise BizLogicError(message=f"Travel Group not found for {location}")
+        
+        formgroup_id = travel_group.get('formGroupId')
+        self._log(f"Waiting for group button to render: {formgroup_id}")
+        btn_selector = f'tag:a@@data-testid=btn-select-group'            
+        self._log(f"Select group_id={formgroup_id} via JS...")
+        self.page.ele(btn_selector).click(by_js=True)
+        
+        self._log("Waiting for url redirect...")
+        self.page.wait.url_change('travel-groups', exclude=True, timeout=45)
+        time.sleep(2)
+
+        if "travel-groups" in self.page.url or "auth" in self.page.url:
+            raise BizLogicError(message="Redirect to service-level Failed!")
+        
+        btn_selector = 'tag:button@@data-testid=btn-add-applicant'
+        if not self.page.wait.ele_displayed(btn_selector, timeout=10):
+            btn_selector = 'tag:button@@data-testid=btn-max-number-of-applicants'
+            if not self.page.ele(btn_selector):
+                raise BizLogicError(message=f"Can't find selector={btn_selector}")
+        self.page.ele(btn_selector).click()
+        time.sleep(6)
+        
+        visa_type = self.account_detail.get("visa_type")
+        if visa_type:
+            btn = self.page.ele('tag:button@@data-testid=input-visa-type')
+            btn.scroll.to_see(center=True)
+            btn.click()
+            time.sleep(0.5)
+            self.page.ele(f'tag:span@@text():{visa_type}').click(by_js=True)
+            time.sleep(0.5)
 
+        tavel_purpose = self.account_detail.get("travel_purpose")
+        if tavel_purpose:
+            btn = self.page.ele('tag:button@@data-testid=input-travel-purpose')
+            btn.scroll.to_see(center=True)
+            btn.click()
+            time.sleep(0.5)
+            self.page.ele(f'tag:span@@text():{tavel_purpose}').click(by_js=True)
+            time.sleep(0.5)
+
+        application_form_id = self.account_detail.get('application_form_id')
+        if application_form_id:
+            ele = self.page.ele('tag:input@@data-testid=f_cai')
+            ele.scroll.to_see(center=True)
+            ele.input(application_form_id)
+
+        last_name = self.account_detail.get('last_name')
+        if last_name:
+            ele = self.page.ele('tag:input@@data-testid=f_pers_surnames')
+            ele.scroll.to_see(center=True)
+            ele.input(last_name.upper())
+
+        first_name = self.account_detail.get('first_name')
+        if first_name:
+            ele = self.page.ele('tag:input@@data-testid=f_pers_givennames')
+            ele.scroll.to_see(center=True)
+            ele.input(first_name.upper())
+
+        gender = self.account_detail.get('gender')
+        if gender:
+            gender = gender.capitalize()
+            ele = self.page.ele(f'tag:label@@text():{gender}')
+            ele.scroll.to_see(center=True)
+            ele.click()
+            
+        fill_date_field(self.page, 'tag:input@@data-testid=f_pers_birth_date', self.account_detail.get('birthday'))
+
+        nationality = self.account_detail.get('nationality')
+        if nationality:
+            nationality = nationality.title()
+            btn = self.page.ele('tag:label@@for=f_pers_nationality').next()
+            btn.scroll.to_see(center=True)
+            btn.click()
+            time.sleep(0.5)
+            self.page.ele(f'tag:li@@role=option@@text():{nationality}').click(by_js=True)
+            time.sleep(0.5)
+            
+        province_residence = self.account_detail.get('province_residence')
+        if province_residence:
+            province_residence = province_residence.title()
+            btn = self.page.ele('tag:label@@for=f_pers_province').next()
+            btn.scroll.to_see(center=True)
+            btn.click()
+            time.sleep(0.5)
+            self.page.ele(f'tag:li@@role=option@@text():{province_residence}').click(by_js=True)
+            time.sleep(0.5)
+
+        passport_type = self.account_detail.get('passport_type')
+        if passport_type:
+            btn = self.page.ele('tag:label@@for=f_identity_type').next()
+            btn.scroll.to_see(center=True)
+            btn.click()
+            time.sleep(0.5)
+            self.page.ele(f'tag:li@@role=option@@text():{passport_type}').click(by_js=True)
+            time.sleep(0.5)
+            
+        passport_no = self.account_detail.get('passport_no')
+        if passport_no:
+            ele = self.page.ele('tag:input@@data-testid=f_pass_num')
+            ele.scroll.to_see(center=True)
+            ele.input(passport_no.upper())
+            
+        phone_country_code = self.account_detail.get('phone_country_code')
+        phone_number = self.account_detail.get('phone_number')
+        if phone_country_code:
+            div = self.page.ele('tag:label@@for=f_pers_mobile_phone').next()
+            btn = div.ele('tag:button')
+            btn.scroll.to_see(center=True)
+            btn.click()
+            time.sleep(0.5)
+            self.page.ele(f'tag:li@@role=option@@text():+{phone_country_code}').click(by_js=True)
+            time.sleep(0.5)
+            div.ele('tag:input@@type:tel').input(phone_number)
+
+        # 使用封装好的日期输入函数
+        fill_date_field(self.page, 'tag:input@@data-testid=fi_trav_origin_departure_date', self.account_detail.get('departure_origin_date'))
+        fill_date_field(self.page, 'tag:input@@data-testid=f_trav_departure_date', self.account_detail.get('arrival_schengen_area_date'))
+        fill_date_field(self.page, 'tag:input@@data-testid=f_trav_arrival_date', self.account_detail.get('departure_schengen_area_date'))
+            
+        submit_btn = self.page.ele('tag:button@@data-testid=btn-submit')
+        submit_btn.scroll.to_see(center=True)
+        time.sleep(1)
+        submit_btn.click()
+        time.sleep(6)
+        submit_btn = self.page.ele('tag:button@@text():Confirm')
+        submit_btn.scroll.to_see(center=True)
+        submit_btn.click()
+                
     def cleanup(self):
         """清理浏览器进程和缓存文件夹"""
         self._log("Cleaning up resources...")
@@ -233,18 +458,37 @@ if __name__ == "__main__":
     }
     
     CAPSOLVER_KEY = "CAP-5441DD341DD3CC2FAEF0BE6FE493EE9A"
-    
-    TARGET_EMAIL = "lisi39@gmail-app.com"
-    TARGET_PWD = "Visafly@111"
-    TARGET_ISSUER = "cnCNG2fr"
-    
+    TLS_URL =  "https://visas-fr.tlscontact.com/visa/cn/cnCNG2fr/home"
+    ACCOUNT_DETAIL = {
+        "email": "lisi103@gmail-app.com",
+        "pwd": "Visafly@111",
+        "location": "Chengdu",
+        "visa_type": "Short stay (<90 days) - Tourism",
+        "travel_purpose": "Tourism / Private visit",
+        "application_form_id": "FRA1CA20260420996",
+        "last_name": "Song",
+        "first_name": "Xiao",
+        "gender": "Male",
+        "birthday": "1998-12-18",
+        "nationality": "China",
+        "province_residence": "Sichuan",
+        "passport_type": "Ordinary passport",
+        "passport_no": "EJ8628293",
+        "phone_country_code": "86",
+        "phone_number": "17386068917",
+        "departure_origin_date": "2026-05-26",
+        "arrival_schengen_area_date": "2026-05-26",
+        "departure_schengen_area_date": "2026-05-28"
+    }
     # ============================================
-
-    bot = TlsRegistrator(proxy_config=PROXY_CONFIG, capsolver_key=CAPSOLVER_KEY)
-    now_utc = datetime.utcnow()
-    formatted_utc_time = (now_utc - timedelta(minutes=4)).strftime("%Y-%m-%d %H:%M:%S")
-    # success = bot.register(email=TARGET_EMAIL, password=TARGET_PWD, issuer_id=TARGET_ISSUER)
-    # if not success:
-    #     print("\n--> 流程完成:账号注册失败,请检查日志。")
-        
-    bot.activate(email=TARGET_EMAIL, sent_at=formatted_utc_time)
+    try:
+        bot = TlsRegistrator(TLS_URL, proxy_config=PROXY_CONFIG, capsolver_key=CAPSOLVER_KEY, account_detail=ACCOUNT_DETAIL)
+        bot.init_browser()
+        now_utc = datetime.utcnow()
+        sent_at = now_utc.strftime("%Y-%m-%d %H:%M:%S")
+        bot.register() 
+        bot.activate(sent_at=sent_at)
+        bot.make_account_useful()
+    except Exception as e:
+        print(f'Exception Info={e}')
+        time.sleep(3600)

+ 1 - 1
utils/cloudflare_bypass_for_scraping.py

@@ -108,7 +108,7 @@ class CloudflareBypasser:
                     self.log_message("Waiting room timeout (1h).")
                     break
                 self.log_message("In Waiting Room... Waiting for auto-refresh.")
-                time.sleep(30)
+                time.sleep(10)
             else:
                 break
             

+ 1 - 1
utils/mouse.py

@@ -31,7 +31,7 @@ from typing import Optional, Tuple
 
 from DrissionPage import ChromiumPage
 
-from math_utils import (
+from utils.math_utils import (
     bezier_2d,
     fitts_duration,
     minimum_jerk,

+ 1 - 1
utils/scroll.py

@@ -27,7 +27,7 @@ from enum import Enum
 from dataclasses import dataclass
 from typing import Optional, Tuple
 from DrissionPage import ChromiumPage
-from math_utils import CubicBezier
+from utils.math_utils import CubicBezier
 
 # ==========================================
 # 1. 枚举与配置类