def handle_turnstile(self, tab=None, max_retries: int = 2, retry_interval: tuple = (1, 2)) -> bool: """ 处理Turnstile验证 Args: tab: 浏览器标签对象 max_retries: 最大重试次数 retry_interval: 重试间隔范围(最小值, 最大值) Returns: bool: 验证是否成功 Raises: TurnstileError: 验证过程中的异常 """ # 如果没有传入tab参数,则使用实例的tab属性 tab = tab or self.tab # 记录开始检测Turnstile验证的日志 logging.info(get_translation("detecting_turnstile")) # 保存验证开始前的屏幕截图 save_screenshot(tab, "start") # 初始化重试计数器 retry_count = 0 try: # 在最大重试次数内循环尝试验证 while retry_count < max_retries: # 增加重试计数 retry_count += 1 # 记录当前是第几次尝试验证 logging.debug(get_translation("retry_verification", count=retry_count)) try: # 初始化元素变量 element = None try: # 尝试通过层级结构定位到Turnstile验证框的容器元素 element = ( tab.ele(".main-content") # 找到 .main-content 元素 .ele("tag:div") # 找到第一个子 div .ele("tag:div") # 找到第二个子 div .ele("tag:div") # 找到第三个子 div ) except Exception as e: # 如果无法通过第一种方式找到元素,忽略异常继续执行 pass if element: # 如果找到了容器元素,则在其中定位验证框的输入元素 challenge_check = ( element .shadow_root.ele("tag:iframe") # 找到shadow DOM中的iframe .ele("tag:body") # 找到iframe中的body .sr("tag:input") # 找到body中的input元素 ) else: # 如果没有找到容器元素,则尝试另一种方式定位验证框 challenge_check = ( tab.ele("@id=cf-turnstile", timeout=2) # 通过id直接找到turnstile元素 .child() # 获取其子元素 .shadow_root.ele("tag:iframe") # 找到shadow DOM中的iframe .ele("tag:body") # 找到iframe中的body .sr("tag:input") # 找到body中的input元素 ) if challenge_check: # 如果找到了验证输入元素,记录日志 logging.info(get_translation("detected_turnstile")) # 点击前随机延迟,模拟人工操作 time.sleep(random.uniform(1, 3)) # 点击验证元素触发验证 challenge_check.click() # 等待验证处理 time.sleep(2) # 保存点击验证后的屏幕截图 save_screenshot(tab, "clicked") # 检查验证是否成功 if check_verification_success(tab): # 验证成功,记录日志 logging.info(get_translation("turnstile_verification_passed")) # 保存验证成功的屏幕截图 save_screenshot(tab, "success") # 返回验证成功 return True except Exception as e: # 记录当前尝试失败的详细信息 logging.debug(f"Current attempt unsuccessful: {str(e)}") # 再次检查验证是否已经成功(可能在异常处理过程中已经通过验证) if check_verification_success(tab): # 返回验证成功 return True # 在下一次尝试前随机延迟 time.sleep(random.uniform(*retry_interval)) # 超过最大重试次数,验证失败 logging.error(get_translation("verification_failed_max_retries", max_retries=max_retries)) # 提供额外的帮助信息,引导用户访问开源项目 logging.error( "Please visit the open source project for more information: https://github.com/wangffei/wf-cursor-auto-free.git" ) # 保存验证失败的屏幕截图 save_screenshot(tab, "failed") # 返回验证失败 return False except Exception as e: # 捕获整个验证过程中的异常 # 构建错误信息 error_msg = get_translation("turnstile_exception", error=str(e)) # 记录错误日志 logging.error(error_msg) # 保存发生错误时的屏幕截图 save_screenshot(tab, "error") # 抛出TurnstileError异常 raise TurnstileError(error_msg)