import asyncio import json import os from playwright.async_api import async_playwright from utils.stealth import stealth_async class Authenticator: def __init__(self, auth_file="auth_state.json"): self.auth_file = auth_file async def login(self, initial_url="https://weidian.com/"): """ 打开浏览器由用户手动扫码登录。 登录成功后保存 session state。 """ async with async_playwright() as p: browser = await p.chromium.launch(headless=False, args=['--disable-gpu']) # 模拟 iPhone 13 配置以确保显示手机版界面 device = p.devices['iPhone 13'] context = await browser.new_context(**device) page = await context.new_page() await stealth_async(page) await page.goto(initial_url) print("请在浏览器中完成登录(扫码等操作)...") # 等待用户手动登录,直到 cookie 中出现登录凭证或 URL 变化 # 这里简单处理,等待用户按回车确认已登录 await asyncio.get_event_loop().run_in_executor(None, input, "登录完成后请在这里按回车控制台继续...") # 保存状态 storage = await context.storage_state(path=self.auth_file) print(f"登录状态已保存至 {self.auth_file}") await browser.close() def has_auth(self): return os.path.exists(self.auth_file) async def get_context(self, playwright_instance, headless=False): """ 创建一个带有已保存状态的 context,并模拟手机环境 """ browser = await playwright_instance.chromium.launch(headless=headless, args=['--disable-gpu']) # 模拟 iPhone 13 配置 device = playwright_instance.devices['iPhone 13'] if self.has_auth(): context = await browser.new_context( **device, storage_state=self.auth_file ) else: context = await browser.new_context(**device) return browser, context