From 389a10351e48e29e587811d7aa9ec62b01a30dea Mon Sep 17 00:00:00 2001 From: mzl Date: Mon, 12 Jan 2026 19:42:43 +0800 Subject: [PATCH] ts --- app/web.py | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/app/web.py b/app/web.py index d053668..82a837a 100644 --- a/app/web.py +++ b/app/web.py @@ -189,10 +189,35 @@ def write_users_txt(users: List[str]) -> None: os.replace(tmp, path) -def require_browser() -> Browser: - if app_state.browser is None: - raise HTTPException(status_code=500, detail="Browser not ready") - return app_state.browser +async def ensure_browser() -> Browser: + """按需启动浏览器(懒启动),避免服务启动阶段因为未安装 Chromium 而直接崩溃。""" + if app_state.browser is not None: + return app_state.browser + + # 初始化 playwright + if app_state.playwright is None: + app_state.playwright = await async_playwright().start() + + try: + # 这里不强制指定 channel,交给 Playwright 选择已安装的 Chromium + app_state.browser = await app_state.playwright.chromium.launch( + headless=True, + args=[ + "--no-sandbox", + "--disable-dev-shm-usage", + ], + ) + log_manager.append("INFO", "Browser launched (lazy init)") + return app_state.browser + except Exception as e: + # 给出明确的修复提示 + msg = ( + f"Browser not ready: {e}. " + "请先在运行环境执行:`playwright install chromium`。" + ) + log_manager.append("ERROR", msg) + raise HTTPException(status_code=500, detail=msg) + # ========================= @@ -279,7 +304,7 @@ async def import_users_from_txt(): total_lines = len(raw_lines) - browser = require_browser() + browser = await ensure_browser() imported_ids: List[str] = [] duplicates = 0 @@ -379,7 +404,7 @@ async def open_login(): 说明:前端 window.open 打开的页面不会影响服务端 Playwright 的登录态。 正确使用方式:在部署环境(Docker + VNC)里打开 VNC 浏览器扫码登录。 """ - browser = require_browser() + browser = await ensure_browser() await auth_manager.open_login_page(browser) return { "login_url": config.LOGIN_URL, @@ -389,7 +414,7 @@ async def open_login(): @app.post("/api/login/verify") async def verify_login(): - browser = require_browser() + browser = await ensure_browser() ok, msg = await auth_manager.verify_login(browser) meta = auth_manager.load_auth_meta() return { @@ -421,7 +446,7 @@ async def start_scraping(request: StartRequest, background_tasks: BackgroundTask raise HTTPException(status_code=400, detail="用户列表为空,请先导入 users.txt") # 启动前校验登录态(单账号) - browser = require_browser() + browser = await ensure_browser() ok, msg = await auth_manager.verify_login(browser) if not ok: raise HTTPException(status_code=400, detail=f"未登录或登录失效:{msg}")