This commit is contained in:
2026-01-24 07:22:10 +08:00
parent c6ab6b3123
commit d93383fe23

View File

@@ -380,6 +380,108 @@ def generate_random_birthday():
day = random.randint(1, max_day)
return str(year), f"{month:02d}", f"{day:02d}"
def _detect_page_language(page) -> str:
"""检测页面语言
Returns:
str: 'zh' 中文, 'en' 英文
"""
try:
html = page.html
# 检查中文关键词
chinese_keywords = ['确认', '继续', '登录', '注册', '验证', '邮箱', '密码', '姓名', '生日']
for keyword in chinese_keywords:
if keyword in html:
return 'zh'
return 'en'
except Exception:
return 'en' # 默认英文
def _input_birthday_precise(page, birth_year: str, birth_month: str, birth_day: str) -> bool:
"""精确输入生日 (使用 data-type 选择器定位输入框)
中文界面: yyyy/mm/dd (年/月/日)
英文界面: mm/dd/yyyy (月/日/年)
Args:
page: 浏览器页面对象
birth_year: 年份 (如 "2000")
birth_month: 月份 (如 "07")
birth_day: 日期 (如 "15")
Returns:
bool: 是否成功
"""
try:
# 使用 data-type 属性精确定位三个输入框
year_input = page.ele('css:[data-type="year"]', timeout=5)
month_input = page.ele('css:[data-type="month"]', timeout=3)
day_input = page.ele('css:[data-type="day"]', timeout=3)
if not all([year_input, month_input, day_input]):
log_progress("⚠ 未找到完整的生日输入框 (data-type),尝试备用方案...")
return False
# 检测页面语言
lang = _detect_page_language(page)
log_progress(f"生日: {birth_year}-{birth_month}-{birth_day} (界面: {lang})")
# 根据语言决定输入顺序
if lang == 'zh':
# 中文: 年 -> 月 -> 日
input_order = [(year_input, birth_year),
(month_input, birth_month),
(day_input, birth_day)]
else:
# 英文: 月 -> 日 -> 年
input_order = [(month_input, birth_month),
(day_input, birth_day),
(year_input, birth_year)]
# 按顺序输入
for input_elem, value in input_order:
try:
input_elem.click()
time.sleep(0.15)
input_elem.input(value, clear=True)
time.sleep(0.2)
except Exception as e:
log_progress(f"⚠ 生日字段输入异常: {e}")
return False
log_progress("✓ 生日已输入 (精确模式)")
return True
except Exception as e:
log_progress(f"⚠ 精确生日输入失败: {e}")
return False
def _input_birthday_fallback(page, birth_year: str, birth_month: str, birth_day: str):
"""备用生日输入方式 (Tab 键切换 + 逐字符输入)
Args:
page: 浏览器页面对象
birth_year: 年份
birth_month: 月份
birth_day: 日期
"""
log_progress(f"生日: {birth_year}-{birth_month}-{birth_day} (备用模式)")
# 使用 Tab 键切换到生日字段
page.actions.key_down('Tab').key_up('Tab')
time.sleep(0.3)
# 逐字符输入
birth_str = birth_year + birth_month + birth_day
for digit in birth_str:
page.actions.type(digit)
time.sleep(0.1)
log_progress("✓ 生日已输入 (备用模式)")
# 地址格式: (街道, 邮编, 城市)
SEPA_ADDRESSES = [
# 柏林
@@ -1250,16 +1352,12 @@ def run_main_process():
name_input.input(real_name)
log_progress(f"姓名: {real_name}")
# 使用 Tab 键切换到生日字段
page.actions.key_down('Tab').key_up('Tab')
# 生成随机生日并输入
# 生成随机生日
birth_year, birth_month, birth_day = generate_random_birthday()
birth_str = birth_year + birth_month + birth_day
log_progress(f"生日: {birth_year}-{birth_month}-{birth_day}")
for digit in birth_str:
page.actions.type(digit)
time.sleep(0.1)
# 优先使用精确输入,失败则使用备用方案
if not _input_birthday_precise(page, birth_year, birth_month, birth_day):
_input_birthday_fallback(page, birth_year, birth_month, birth_day)
time.sleep(1.5)
# 点击继续/完成注册(使用 type=submit
@@ -1268,6 +1366,53 @@ def run_main_process():
time.sleep(2)
log_progress(f"当前URL: {page.url}")
# === 检测提交后是否有错误或需要额外操作 ===
submit_success = False
for check_attempt in range(10):
current_url = page.url
# 检查是否已跳转出 about-you 页面
if 'about-you' not in current_url:
log_progress(f"✓ 页面已跳转: {current_url[:50]}...")
submit_success = True
break
# 检查是否有错误提示
try:
error_elem = page.ele('css:[role="alert"], [class*="error"], [class*="Error"]', timeout=1)
if error_elem and error_elem.text:
log_progress(f"⚠ 发现错误提示: {error_elem.text[:50]}")
except:
pass
# 检查是否有未勾选的 checkbox如服务条款
try:
unchecked = page.ele('css:input[type="checkbox"]:not(:checked)', timeout=1)
if unchecked:
log_progress("发现未勾选的选项,尝试勾选...")
unchecked.click()
time.sleep(0.5)
# 重新点击提交
final_reg_btn = page.ele('css:button[type="submit"]', timeout=5)
if final_reg_btn:
final_reg_btn.click()
time.sleep(2)
except:
pass
# 检查是否有 CAPTCHA
try:
captcha = page.ele('css:iframe[src*="captcha"], iframe[src*="recaptcha"], [class*="captcha"]', timeout=1)
if captcha:
log_progress("⚠ 检测到 CAPTCHA需要人工处理或等待...")
except:
pass
time.sleep(1)
if not submit_success:
log_progress(f"⚠ 提交后仍在 about-you 页面当前URL: {page.url}")
# =======================================================
# 【关键节点】等待进入主页后再执行 JS 跳转到支付页
# =======================================================
@@ -1611,14 +1756,13 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict:
name_input = page.ele('@name=name', timeout=20)
name_input.input(real_name)
log_progress(f"姓名: {real_name}")
page.actions.key_down('Tab').key_up('Tab')
# 生成随机生日
birth_year, birth_month, birth_day = generate_random_birthday()
birth_str = birth_year + birth_month + birth_day
log_progress(f"生日: {birth_year}-{birth_month}-{birth_day}")
for digit in birth_str:
page.actions.type(digit)
time.sleep(0.1)
# 优先使用精确输入,失败则使用备用方案
if not _input_birthday_precise(page, birth_year, birth_month, birth_day):
_input_birthday_fallback(page, birth_year, birth_month, birth_day)
time.sleep(1.5)
final_reg_btn = page.ele('css:button[type="submit"]', timeout=20)
@@ -1626,6 +1770,53 @@ def run_single_registration(progress_callback=None, step_callback=None) -> dict:
time.sleep(2)
log_progress(f"当前URL: {page.url}")
# === 检测提交后是否有错误或需要额外操作 ===
submit_success = False
for check_attempt in range(10):
current_url = page.url
# 检查是否已跳转出 about-you 页面
if 'about-you' not in current_url:
log_progress(f"✓ 页面已跳转: {current_url[:50]}...")
submit_success = True
break
# 检查是否有错误提示
try:
error_elem = page.ele('css:[role="alert"], [class*="error"], [class*="Error"]', timeout=1)
if error_elem and error_elem.text:
log_progress(f"⚠ 发现错误提示: {error_elem.text[:50]}")
except:
pass
# 检查是否有未勾选的 checkbox如服务条款
try:
unchecked = page.ele('css:input[type="checkbox"]:not(:checked)', timeout=1)
if unchecked:
log_progress("发现未勾选的选项,尝试勾选...")
unchecked.click()
time.sleep(0.5)
# 重新点击提交
final_reg_btn = page.ele('css:button[type="submit"]', timeout=5)
if final_reg_btn:
final_reg_btn.click()
time.sleep(2)
except:
pass
# 检查是否有 CAPTCHA
try:
captcha = page.ele('css:iframe[src*="captcha"], iframe[src*="recaptcha"], [class*="captcha"]', timeout=1)
if captcha:
log_progress("⚠ 检测到 CAPTCHA需要人工处理或等待...")
except:
pass
time.sleep(1)
if not submit_success:
log_progress(f"⚠ 提交后仍在 about-you 页面当前URL: {page.url}")
# 等待进入主页 - 改进检测逻辑
step_cb("等待进入主页...")
log_status("订阅", "等待进入 ChatGPT 主页...")