fix(tencent): 登录成功改为 cookie 检测优先(ww_datasalt/ww_bizuin/wxuin/slave_sid),修复扫码确认后 DOM/URL 检测不到的问题

This commit is contained in:
Qiufeng
2026-08-21 17:07:18 +08:00
parent 583a7a3465
commit 9295e715b5
+35 -39
View File
@@ -235,51 +235,45 @@ async def _save_tencent_qrcode(page: Page, account_file: str, previous_qrcode_pa
return qrcode_info return qrcode_info
async def _is_tencent_login_completed(page: Page) -> bool: # 微信扫码登录成功后,视频号助手(channels.weixin.qq.com)域下必然种下这些登录态 cookie;
# 仍在登录页(含扫码 iframe)=> 未登录 # 用 cookie 判定登录成功最可靠,不依赖页面 DOM/URL(登录后落地页可能停在首页、残留 iframe 等)
_TENCENT_LOGIN_COOKIE_MARKERS = {"ww_datasalt", "ww_bizuin", "wxuin", "slave_sid", "slave_user"}
async def _has_tencent_login_cookie(context) -> bool:
try:
cookies = await context.cookies()
names = {c["name"] for c in cookies}
return bool(names & _TENCENT_LOGIN_COOKIE_MARKERS)
except Exception:
return False
async def _is_tencent_login_completed(page: Page, context=None) -> bool:
# 首选:登录态 cookie 出现即视为成功(扫码+手机确认后浏览器必种 cookie)
if context is not None and await _has_tencent_login_cookie(context):
return True
current_url = page.url or "" current_url = page.url or ""
# 仍在登录页 => 未登录
if "login.html" in current_url: if "login.html" in current_url:
return False return False
# 页面内还存在微信扫码登录 iframe => 未登录 # 已跳到平台页(首页/发布页/列表页):只要没有可见的二维码容器就算成功
try: # 注意:残留的扫码 iframe 只隐藏未移除时也会在 page.frames 里,不能作为否决条件
for fr in page.frames:
if "open.weixin.qq.com/connect/qrconnect" in (fr.url or ""):
return False
except Exception:
pass
# 页面内还存在登录二维码容器 => 未登录
login_markers = [
page.locator("div.login-qrcode-wrap").first,
page.locator("div.qrcode-wrap").first,
page.locator('span:has-text("微信扫码登录 视频号助手")').first,
]
for marker in login_markers:
try:
if await marker.count() and await marker.is_visible():
return False
except Exception:
continue
# 已离开登录页且登录框/二维码均消失 => 视为登录成功
# (视频号登录后通常停在 /platform 首页,不一定跳到 post/create 或 post/list)
if current_url.startswith(TENCENT_HOME_URL) or current_url.startswith(TENCENT_UPLOAD_URL) or current_url.startswith(TENCENT_MANAGE_URL): if current_url.startswith(TENCENT_HOME_URL) or current_url.startswith(TENCENT_UPLOAD_URL) or current_url.startswith(TENCENT_MANAGE_URL):
for marker in [
page.locator("div.login-qrcode-wrap").first,
page.locator("div.qrcode-wrap").first,
page.locator('span:has-text("微信扫码登录 视频号助手")').first,
]:
try:
if await marker.count() and await marker.is_visible():
return False
except Exception:
continue
return True return True
# 兜底:出现发布相关按钮也视为成功
publish_markers = [
page.locator('div:has-text("发表视频")').first,
page.locator('button:has-text("发表")').first,
page.locator('button:has-text("保存草稿")').first,
]
for marker in publish_markers:
try:
if await marker.count() and await marker.is_visible():
return True
except Exception:
continue
return False return False
@@ -360,6 +354,7 @@ async def _refresh_tencent_qrcode(page: Page) -> None:
async def _wait_for_tencent_login( async def _wait_for_tencent_login(
page: Page, page: Page,
context,
account_file: str, account_file: str,
qrcode_info: dict | None, qrcode_info: dict | None,
qrcode_callback=None, qrcode_callback=None,
@@ -369,7 +364,7 @@ async def _wait_for_tencent_login(
qrcode_path = Path(qrcode_info["image_path"]) if qrcode_info else None qrcode_path = Path(qrcode_info["image_path"]) if qrcode_info else None
scanned_logged = False scanned_logged = False
for _ in range(max_checks): for _ in range(max_checks):
if await _is_tencent_login_completed(page): if await _is_tencent_login_completed(page, context):
tencent_logger.info(_msg("🥳", f"扫码成功,已经跳转到登录后页面: {page.url}")) tencent_logger.info(_msg("🥳", f"扫码成功,已经跳转到登录后页面: {page.url}"))
return _build_login_result(True, "success", "视频号扫码登录成功", account_file, qrcode_info, page.url) return _build_login_result(True, "success", "视频号扫码登录成功", account_file, qrcode_info, page.url)
@@ -433,6 +428,7 @@ async def tencent_cookie_gen(
tencent_logger.info(_msg("🧍", "请扫码,小人正在耐心等待登录完成")) tencent_logger.info(_msg("🧍", "请扫码,小人正在耐心等待登录完成"))
result = await _wait_for_tencent_login( result = await _wait_for_tencent_login(
page, page,
context,
account_file, account_file,
qrcode_info, qrcode_info,
qrcode_callback=qrcode_callback, qrcode_callback=qrcode_callback,