chore: auto release commit (2026-09-15 01:27:04)
Some checks failed
技能自动化发布 / release (push) Failing after 4s

This commit is contained in:
2026-09-15 01:27:05 +08:00
parent 430274dbf9
commit ebea77b5f2
5 changed files with 176 additions and 27 deletions

View File

@@ -529,6 +529,76 @@ def _fill_root_login(page) -> bool:
return True
def _fill_demo_on_spa_login(page) -> bool:
"""v1.1.27:SPA 二级登录页(/industries/campus/smartcampus/login)
input 默认**不预填**(与根域不同),必须主动 fill demo/123456 再点登录。
selector 优先级:
- user: `#jc-user` → `input[type='tel']` → `input[autocomplete='username']`
- pass: `#jc-pass` → `input[type='password']` → `input[autocomplete='current-password']`
按钮文本优先级:Sign in → 登录 → Login → signin → submit[type]。
返回是否成功点登录按钮。
"""
# 找 user input
user_loc = None
for sel in ("#jc-user", "input[type='tel']", "input[autocomplete='username']"):
loc = page.locator(sel).first
if loc.count() > 0:
user_loc = loc
break
if user_loc is None:
logger.warning(
"platform_collector._fill_demo_on_spa_login: 找不到 user input "
"(#jc-user / tel / autocomplete=username 全 miss)"
)
return False
# 找 pass input
pass_loc = None
for sel in ("#jc-pass", "input[type='password']", "input[autocomplete='current-password']"):
loc = page.locator(sel).first
if loc.count() > 0:
pass_loc = loc
break
if pass_loc is None:
logger.warning(
"platform_collector._fill_demo_on_spa_login: 找不到 pass input"
)
return False
user_loc.fill("demo")
pass_loc.fill("123456")
logger.info(
"platform_collector: SPA 二级登录页 fill demo/123456 完成"
)
# 找登录按钮
btn = None
btn_text_used = ""
for txt in ("Sign in", "登录", "Login", "signin"):
loc = page.locator(f"button:has-text('{txt}')").first
if loc.count() > 0:
btn = loc
btn_text_used = txt
break
if btn is None:
btn = page.locator("button[type='submit']").first
btn_text_used = "submit"
if btn is None or btn.count() == 0:
logger.warning(
"platform_collector._fill_demo_on_spa_login: 找不到登录按钮"
)
return False
logger.info(
"platform_collector: SPA 二级登录页点 %s 按钮(demo/123456)",
btn_text_used,
)
btn.click()
return True
def _click_campus_link(page) -> bool:
"""在 /select 页面点智慧校园 tile,返回是否点中。"""
link = page.locator("a[href*='/industries/campus']").first
@@ -743,44 +813,52 @@ def collect_all(
f"(请用 --show-browser 重试)"
)
# 4. 登录完成 → 等 URL 真正稳定到 /app/ 或 /select(最多 30s,**不做任何操作**)
# v1.1.22:sandbox 登录后会先跳 /select,再自动跳 /app/home,
# 所以两个 URL 都算"SPA 已路由"
if not _wait_for_url_stable(page, ("/app/", "/select"), max_wait_sec=30):
# 4. v1.1.27:等 URL 跳到任一「SPA 已路由」状态(最多 30s,**不做任何操作**)
# - /app/ = 已到 SPA 主页
# - /select = sandbox 中间页
# - /login 或 /signin = sandbox 又把人踢回登录页(根域登录后常见,
# sandbox 会跳到 /industries/campus/smartcampus/login SPA 二级登录页)
# - 如果 URL 跳到 login/signin,**立即**退出 30 秒等待(不再干等),
# 让 4.5 处理。否则会等满 30 秒才发现要进 SPA 登录兜底,造成卡顿。
spa_url_seen = False
if not _wait_for_url_stable(
page, ("/app/", "/select", "/login", "/signin"), max_wait_sec=30,
):
logger.warning(
"platform_collector: 登录后 30s 内 URL 未稳定到 /app/或 /select(当前 URL=%s)",
"platform_collector: 登录后 30s 内 URL 未稳定到 /app/、/select、"
"/login 或 /signin(当前 URL=%s)",
page.url,
)
# 不强行 reload —— 让用户决定是否手工刷新
# 4.5. v1.1.24:sandbox 可能登录后把人踢回 SPA 二级登录页
# (/industries/campus/smartcampus/login)。如果 URL 落在
# 这个二级登录页,再走一次 _try_auto_sign_in(已经扩展支持
# 中文「登录」按钮);若 SPA 登录页 input 有预填账号 → 自动点;
# 若 input 空 → 等用户输入并**自己点登录**(脚本不抢按钮)。
# 4.5. v1.1.24/27:URL 落在 SPA 二级登录页 → 自动填 demo/123456 再登录
# sandbox SPA 登录页 input 默认**不预填**(与根域不同),
# 所以 _try_auto_sign_in 不会自动点 —— 必须显式 fill demo/123456。
cur_url_after_stable = page.url.lower()
if "/login" in cur_url_after_stable or "/signin" in cur_url_after_stable:
logger.warning(
"platform_collector: 登录后仍落在登录页(%s),"
"v1.1.24 触发 SPA 二级登录兜底",
"platform_collector: 登录后落在 SPA 二级登录页(%s),"
"v1.1.27 触发 demo/123456 自动 fill",
page.url,
)
spa_auto = _try_auto_sign_in(page, wait_input_sec=2)
if spa_auto:
spa_filled = _fill_demo_on_spa_login(page)
if spa_filled:
logger.info(
"platform_collector: ✅ SPA 二级登录页已自动登录,"
"等 URL 跳到 /app/ 或 /select"
"platform_collector: ✅ SPA 二级登录页 demo/123456 自动填好,"
"已点登录,等 URL 跳到 /app/ 或 /select"
)
_wait_for_url_stable(page, ("/app/", "/select"), max_wait_sec=30)
elif not headless:
if _wait_for_login_inputs_filled(page, wait_sec=human_wait_timeout):
_wait_for_url_stable(page, ("/app/", "/select"), max_wait_sec=30)
else:
_wait_for_manual_login(page, wait_sec=human_wait_timeout)
else:
raise LoginTimeoutError(
f"SPA 二级登录页 input 空且 headless 无法手工登录(URL={page.url})"
)
# demo fill 失败(input 不存在)→ 等用户手工输入
if not headless:
if _wait_for_login_inputs_filled(page, wait_sec=human_wait_timeout):
_wait_for_url_stable(page, ("/app/", "/select"), max_wait_sec=30)
else:
_wait_for_manual_login(page, wait_sec=human_wait_timeout)
else:
raise LoginTimeoutError(
f"SPA 二级登录页 demo fill 失败且 headless 无法手工登录"
f"(URL={page.url})"
)
# 5. v1.1.22:显式跳到 SPA_HOME_URL(/app/home),等侧边栏 link 出现
# 避免 sandbox 在 /select 中间页时直接找 sidebar link 找不到