|
@@ -83,7 +83,7 @@ def _try_click_first_visible(page, selector: str, log, *, label: str = "") -> bo
|
|
|
|
|
|
|
|
|
|
|
|
|
def _click_signup_entry(page, log) -> bool:
|
|
def _click_signup_entry(page, log) -> bool:
|
|
|
- """ChatGPT 首页右上角"注册"按钮。"""
|
|
|
|
|
|
|
+ """ChatGPT 首页右上角"注册"按钮。命中即返回 True;命中后等待 ~1s 让导航开始。"""
|
|
|
candidates = [
|
|
candidates = [
|
|
|
'a[data-testid="signup-button"]',
|
|
'a[data-testid="signup-button"]',
|
|
|
'button[data-testid="signup-button"]',
|
|
'button[data-testid="signup-button"]',
|
|
@@ -94,6 +94,10 @@ def _click_signup_entry(page, log) -> bool:
|
|
|
]
|
|
]
|
|
|
for sel in candidates:
|
|
for sel in candidates:
|
|
|
if _try_click_first_visible(page, sel, log, label=f"signup entry({sel})"):
|
|
if _try_click_first_visible(page, sel, log, label=f"signup entry({sel})"):
|
|
|
|
|
+ try:
|
|
|
|
|
+ page.wait_for_timeout(800)
|
|
|
|
|
+ except Exception:
|
|
|
|
|
+ pass
|
|
|
return True
|
|
return True
|
|
|
|
|
|
|
|
# 文本兜底
|
|
# 文本兜底
|
|
@@ -200,13 +204,41 @@ def _wait_until(predicate: Callable[[], bool], timeout_sec: int, interval_ms: in
|
|
|
|
|
|
|
|
def _fill_signup_email(page, email: str, log):
|
|
def _fill_signup_email(page, email: str, log):
|
|
|
log(f"[signup] === 提交注册邮箱 {email} ===")
|
|
log(f"[signup] === 提交注册邮箱 {email} ===")
|
|
|
|
|
+ # 邮箱页可能由前一步导航触发,需要等一会让 input 挂载
|
|
|
inp, used_sel = _find_visible(page, EMAIL_INPUT_SELECTORS)
|
|
inp, used_sel = _find_visible(page, EMAIL_INPUT_SELECTORS)
|
|
|
if not inp:
|
|
if not inp:
|
|
|
- # 可能仍在首页,先点注册入口
|
|
|
|
|
- if _click_signup_entry(page, log):
|
|
|
|
|
- page.wait_for_load_state("domcontentloaded", timeout=20000)
|
|
|
|
|
- page.wait_for_timeout(1500)
|
|
|
|
|
- inp, used_sel = _find_visible(page, EMAIL_INPUT_SELECTORS)
|
|
|
|
|
|
|
+ # 等最多 8s:要么邮箱框出现,要么 URL 跳到 auth.openai.com 后再继续等
|
|
|
|
|
+ deadline = time.time() + 8
|
|
|
|
|
+ while time.time() < deadline:
|
|
|
|
|
+ inp, used_sel = _find_visible(page, EMAIL_INPUT_SELECTORS)
|
|
|
|
|
+ if inp:
|
|
|
|
|
+ break
|
|
|
|
|
+ time.sleep(0.4)
|
|
|
|
|
+
|
|
|
|
|
+ if not inp:
|
|
|
|
|
+ # 仍找不到 — 只有当确实还停在 chatgpt.com 主页时才补点注册入口(避免点已跳转的页面把表单关掉)
|
|
|
|
|
+ cur_url = (page.url or "").lower()
|
|
|
|
|
+ if "chatgpt.com" in cur_url and "auth" not in cur_url and "/email-verification" not in cur_url:
|
|
|
|
|
+ log(f"[signup] 邮箱框未挂载且仍在 chatgpt.com 主页,补点一次注册入口 url={cur_url}")
|
|
|
|
|
+ if _click_signup_entry(page, log):
|
|
|
|
|
+ page.wait_for_load_state("domcontentloaded", timeout=20000)
|
|
|
|
|
+ page.wait_for_timeout(1500)
|
|
|
|
|
+ # 再等一会
|
|
|
|
|
+ deadline = time.time() + 8
|
|
|
|
|
+ while time.time() < deadline:
|
|
|
|
|
+ inp, used_sel = _find_visible(page, EMAIL_INPUT_SELECTORS)
|
|
|
|
|
+ if inp:
|
|
|
|
|
+ break
|
|
|
|
|
+ time.sleep(0.4)
|
|
|
|
|
+ else:
|
|
|
|
|
+ log(f"[signup] 已离开主页(url={cur_url}),不再点注册入口,仅继续等邮箱框")
|
|
|
|
|
+ deadline = time.time() + 8
|
|
|
|
|
+ while time.time() < deadline:
|
|
|
|
|
+ inp, used_sel = _find_visible(page, EMAIL_INPUT_SELECTORS)
|
|
|
|
|
+ if inp:
|
|
|
|
|
+ break
|
|
|
|
|
+ time.sleep(0.4)
|
|
|
|
|
+
|
|
|
if not inp:
|
|
if not inp:
|
|
|
raise RuntimeError(f"未找到邮箱输入框 URL={page.url}")
|
|
raise RuntimeError(f"未找到邮箱输入框 URL={page.url}")
|
|
|
|
|
|