""" UI 自动化基类占位 (推荐使用 Playwright) """ from playwright.sync_api import sync_playwright from framework.core.logger import get_logger import time logger = get_logger("BaseUI") class BaseUI: def __init__(self, headless=False): self.playwright = None self.browser = None self.context = None self.page = None self.headless = headless def start(self): """启动浏览器并伪装""" self.playwright = sync_playwright().start() # 增加伪装配置 self.browser = self.playwright.chromium.launch( headless=self.headless, args=["--disable-blink-features=AutomationControlled"] ) # 设置真实的 User-Agent user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" self.context = self.browser.new_context(user_agent=user_agent) self.page = self.context.new_page() # 实时打印浏览器控制台日志,方便排查白屏 self.page.on("console", lambda msg: logger.info(f"[BROWSER LOG] {msg.text}")) self.page.on("pageerror", lambda exc: logger.error(f"[BROWSER ERROR] {exc}")) logger.info("Browser started with spoofing and logging") return self.page def stop(self): """关闭浏览器""" if self.browser: self.browser.close() if self.playwright: self.playwright.stop() logger.info("Browser stopped") def navigate(self, url): logger.info(f"Navigate to {url}") # 使用更稳健的加载策略:DOM 加载完即继续,后续靠 wait_for_selector self.page.goto(url, wait_until="domcontentloaded", timeout=30000) # 给 2 秒缓冲时间让脚本执行 time.sleep(2) def click(self, selector, timeout=5000): try: logger.info(f"Clicking: {selector}") self.page.click(selector, timeout=timeout) except Exception as e: self.page.screenshot(path="click_failed.png") logger.error(f"Click failed on {selector}, saved screenshot to click_failed.png") raise e def fill(self, selector, value): logger.info(f"Filling {selector} with value") self.page.fill(selector, value) def wait_for_selector(self, selector, timeout=10000): self.page.wait_for_selector(selector, timeout=timeout)