import logging import time from typing import Optional from playwright.sync_api import Page, TimeoutError as PlaywrightTimeoutError logger = logging.getLogger(__name__) class BrowserUtils: """浏览器操作工具类""" @staticmethod def wait_for_element(page: Page, selector: str, timeout: int = 30000) -> bool: """ 等待元素出现 Args: page: Playwright页面对象 selector: CSS选择器 timeout: 超时时间(毫秒) Returns: bool: 成功返回True,超时返回False """ try: page.wait_for_selector(selector, timeout=timeout) return True except PlaywrightTimeoutError: logger.warning(f"等待元素超时: {selector}") return False @staticmethod def fill_input( page: Page, selector: str, text: str, clear_first: bool = True ) -> bool: """ 填充输入框 Args: page: Playwright页面对象 selector: CSS选择器 text: 要填充的文本 clear_first: 是否先清除原有内容 Returns: bool: 成功返回True,失败返回False """ try: # 等待元素出现 if not BrowserUtils.wait_for_element(page, selector): return False # 如果需要先清除原有内容 if clear_first: page.fill(selector, "") # 填充文本 page.fill(selector, text) return True except Exception as e: logger.error(f"填充输入框时出错: {str(e)}") return False @staticmethod def click_element(page: Page, selector: str, timeout: int = 30000) -> bool: """ 点击元素 Args: page: Playwright页面对象 selector: CSS选择器 timeout: 超时时间(毫秒) Returns: bool: 成功返回True,失败返回False """ try: # 等待元素出现 if not BrowserUtils.wait_for_element(page, selector, timeout): return False # 点击元素 page.click(selector) return True except Exception as e: logger.error(f"点击元素时出错: {str(e)}") return False @staticmethod def get_text(page: Page, selector: str) -> Optional[str]: """ 获取元素文本内容 Args: page: Playwright页面对象 selector: CSS选择器 Returns: str or None: 元素文本内容或None """ try: # 等待元素出现 if not BrowserUtils.wait_for_element(page, selector): return None # 获取文本内容 return page.text_content(selector) except Exception as e: logger.error(f"获取元素文本内容时出错: {str(e)}") return None @staticmethod def take_screenshot(page: Page, path: str) -> bool: """ 截取屏幕截图 Args: page: Playwright页面对象 path: 截图保存路径 Returns: bool: 成功返回True,失败返回False """ try: page.screenshot(path=path) logger.info(f"已保存截图: {path}") return True except Exception as e: logger.error(f"截图时出错: {str(e)}") return False @staticmethod def is_element_visible(page: Page, selector: str) -> bool: """ 检查元素是否可见 Args: page: Playwright页面对象 selector: CSS选择器 Returns: bool: 可见返回True,不可见返回False """ try: return page.is_visible(selector) except Exception: return False