From 9cfc1485774ba4e8b9cadc2dcd343d348f7e7f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Fri, 18 Sep 2026 14:44:26 +0800 Subject: [PATCH] =?UTF-8?q?fix(bili):=20=E5=85=BC=E5=AE=B9=E9=A6=96?= =?UTF-8?q?=E9=A1=B5=E6=96=B0=E7=89=88=20header=20=E7=9A=84=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=85=A5=E5=8F=A3=E9=80=89=E6=8B=A9=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit B 站首页 header 新旧两套实现并行灰度,登录入口选择器不同: - 新版 header:.header-avatar-unlogin-entry - 旧版 header:.right-entry__outside.go-login-btn 内的 .header-login-entry 原代码只匹配旧版,且 header 版本按 cookie 分流(携带过期 SESSDATA 也会 被分到新版),导致未登录场景下点击登录按钮直接 30s 超时。 改为组合选择器,并在等待超时时输出明确的排查提示,替代原先裸的 Playwright traceback。两套 header 的按钮均调用同一个 openMiniLogin(), 弹窗及二维码结构未变,故无需改动。 --- media_platform/bilibili/login.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/media_platform/bilibili/login.py b/media_platform/bilibili/login.py index bd50fe2..bb19af5 100644 --- a/media_platform/bilibili/login.py +++ b/media_platform/bilibili/login.py @@ -29,6 +29,7 @@ import sys from typing import Optional from playwright.async_api import BrowserContext, Page +from playwright.async_api import TimeoutError as PlaywrightTimeoutError from tenacity import (RetryError, retry, retry_if_result, stop_after_attempt, wait_fixed) @@ -36,6 +37,16 @@ import config from base.base_crawler import AbstractLogin from tools import utils +# B 站首页 header 目前新旧两套实现并行灰度,未登录时的登录入口选择器不同: +# - 新版 header:.header-avatar-unlogin-entry +# - 旧版 header:.right-entry__outside.go-login-btn 内部的 .header-login-entry +# 两者点击后都调用 mini-login-v2 的 openMiniLogin(),拉起同一个登录弹窗, +# 弹窗内的二维码仍是 .login-scan-box 里的 img,所以这里只需要兼容入口按钮。 +LOGIN_ENTRY_SELECTORS = [ + ".header-avatar-unlogin-entry", + ".right-entry__outside.go-login-btn .header-login-entry", +] + class BilibiliLogin(AbstractLogin): def __init__(self, @@ -82,10 +93,22 @@ class BilibiliLogin(AbstractLogin): utils.logger.info("[BilibiliLogin.login_by_qrcode] Begin login bilibili by qrcode ...") # click login button - login_button_ele = self.context_page.locator( - "xpath=//div[@class='right-entry__outside go-login-btn']//div" - ) - await login_button_ele.click() + login_entry_selector = ", ".join(LOGIN_ENTRY_SELECTORS) + try: + await self.context_page.wait_for_selector( + selector=login_entry_selector, + state="visible", + timeout=30_000, + ) + except PlaywrightTimeoutError: + utils.logger.error( + "[BilibiliLogin.login_by_qrcode] Login entry not found on the homepage, " + f"selectors tried: {LOGIN_ENTRY_SELECTORS}. " + "Bilibili may have changed the homepage header again, " + "please update LOGIN_ENTRY_SELECTORS in media_platform/bilibili/login.py." + ) + sys.exit() + await self.context_page.locator(login_entry_selector).first.click() await asyncio.sleep(1) # find login qrcode qrcode_img_selector = "//div[@class='login-scan-box']//img"