cursor_auto_register/handle_turnstile_update.py

122 lines
5.8 KiB
Python
Raw Normal View History

2025-05-11 23:06:57 +08:00
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)