从入门到精通介绍Python中Selenium安装使用的完整指南

Written by

in

文章目录
  • 目录
    • 环境准备与基础入门
      • 1. 安装 Selenium 与浏览器驱动
        • 安装 Selenium
        • 安装浏览器驱动
      • 2. Selenium 4.x 新特性
        • 3. WebDriver初始化方法
          • 使用Selenium Manager(推荐,Selenium 4.x)
          • 传统方法(指定驱动路径)
          • 配置浏览器选项
        • 4. 基础浏览器操作
          • 5. 常见浏览器配置
            • 无头模式(Headless)
            • 使用代理
            • 禁用图片加载(提高性能)
        • 元素定位与交互操作
          • 1. 元素定位基础
            • 2. 高级定位策略
              • XPath进阶用法
              • CSS选择器进阶用法
              • 相对定位(Selenium 4.x新特性)
            • 3. 查找多个元素
              • 4. 元素交互操作
                • 5. 元素查找最佳实践
                • 等待机制与异常处理
                  • 1. 等待策略
                    • 隐式等待(Implicit Wait)
                    • 显式等待(Explicit Wait)
                    • 自定义等待条件
                    • 流畅等待(FluentWait)
                  • 2. 异常处理
                    • 常见异常类型
                    • 基本异常处理
                    • 重试机制
                    • 处理StaleElementReferenceException
                    • 使用装饰器处理异常
                  • 3. 等待策略最佳实践
                  • 面向对象封装与框架设计
                    • 1. 页面对象模型(Page Object Model, POM)
                      • 基本POM结构
                      • 使用POM进行测试
                    • 2. 测试框架集成
                      • 与unittest集成
                      • 与pytest集成
                      • 与Behave(BDD)集成
                    • 3. 高级框架设计模式
                      • 工厂模式
                      • 单例模式(驱动管理器)
                      • 策略模式(等待策略)
                    • 4. 配置与日志管理
                      • 配置管理
                      • 日志管理
                  • 进阶技巧与最佳实践
                    • 1. 高级交互操作
                      • ActionChains高级操作
                      • 处理JavaScript事件
                    • 2. 窗口与标签页管理
                      • 3. iframe处理
                        • 4. 文件上传与下载
                          • 文件上传
                          • 文件下载
                        • 5. 截图与日志
                          • 6. 高级断言与验证
                          • 性能优化与调试技巧
                            • 1. 性能测试与优化
                              • 测量页面加载时间
                              • 使用Performance API获取详细性能数据
                              • 优化执行速度
                            • 2. 高级调试技巧

                            # 使用pip安装最新版本
                            pip install selenium
                            
                            # 安装特定版本
                            pip install selenium==4.10.0
                            
                            # 在虚拟环境中安装(推荐)
                            python -m venv selenium_env
                            source selenium_env/bin/activate  # Linux/Mac
                            selenium_envScriptsactivate.bat  # Windows
                            pip install selenium
                            

                            从Selenium 4.0开始,提供了自动管理驱动的功能,但了解手动安装方法仍然很重要:

                            Chrome浏览器:

                            • 访问 ChromeDriver 下载页面
                            • 下载与本地Chrome版本匹配的驱动程序
                            • 将驱动添加到系统PATH中或在代码中指定路径

                            Firefox浏览器:

                            • 访问 GeckoDriver 下载页面
                            • 下载适用于你操作系统的版本
                            • 将驱动添加到系统PATH中或在代码中指定路径

                            Edge浏览器:

                            • 访问 Microsoft Edge Driver 下载页面
                            • 下载与本地Edge版本匹配的驱动程序

                            Safari浏览器:

                            • Safari驱动已内置于macOS中
                            • 需要在Safari浏览器中启用开发者模式

                            Selenium 4.x引入了许多重要的改进和新功能:

                            • 相对定位:允许基于其他元素的位置来查找元素
                            • Service对象:用于更好地管理驱动程序服务
                            • WebDriver Manager:自动管理驱动程序的下载和设置
                            • CDP(Chrome DevTools Protocol)支持:允许访问浏览器特定的功能

                            from selenium import webdriver
                            from selenium.webdriver.chrome.service import Service
                            
                            # 自动管理驱动
                            driver = webdriver.Chrome()
                            

                            from selenium import webdriver
                            from selenium.webdriver.chrome.service import Service
                            
                            # 指定驱动路径
                            service = Service(executable_path='/path/to/chromedriver')
                            driver = webdriver.Chrome(service=service)
                            

                            from selenium import webdriver
                            from selenium.webdriver.chrome.options import Options
                            
                            # 创建Chrome选项对象
                            chrome_options = Options()
                            chrome_options.add_argument("--headless")  # 无头模式
                            chrome_options.add_argument("--window-size=1920,1080")  # 设置窗口大小
                            chrome_options.add_argument("--disable-gpu")  # 禁用GPU加速
                            chrome_options.add_argument("--disable-extensions")  # 禁用扩展
                            chrome_options.add_argument("--proxy-server='direct://'")  # 代理设置
                            chrome_options.add_argument("--proxy-bypass-list=*")  # 绕过代理
                            chrome_options.add_argument("--start-maximized")  # 启动时最大化窗口
                            chrome_options.add_experimental_option("prefs", {
                                "download.default_directory": "/path/to/download/directory",  # 设置下载目录
                                "download.prompt_for_download": False,  # 禁用下载提示
                                "download.directory_upgrade": True,
                                "safebrowsing.enabled": True
                            })
                            
                            # 初始化WebDriver
                            driver = webdriver.Chrome(options=chrome_options)
                            

                            from selenium import webdriver
                            
                            # 初始化WebDriver
                            driver = webdriver.Chrome()
                            
                            # 窗口操作
                            driver.maximize_window()  # 最大化窗口
                            driver.set_window_size(1920, 1080)  # 设置窗口大小
                            driver.set_window_position(0, 0)  # 设置窗口位置
                            
                            # 导航操作
                            driver.get('https://www.example.com')  # 打开URL
                            driver.back()  # 后退
                            driver.forward()  # 前进
                            driver.refresh()  # 刷新页面
                            
                            # 页面信息
                            title = driver.title  # 获取页面标题
                            url = driver.current_url  # 获取当前URL
                            page_source = driver.page_source  # 获取页面源代码
                            
                            # Cookie操作
                            driver.add_cookie({"name": "key", "value": "value"})  # 添加Cookie
                            cookies = driver.get_cookies()  # 获取所有Cookies
                            driver.delete_cookie("key")  # 删除特定Cookie
                            driver.delete_all_cookies()  # 删除所有Cookies
                            
                            # 关闭操作
                            driver.close()  # 关闭当前标签页
                            driver.quit()  # 关闭浏览器,释放资源
                            

                            from selenium import webdriver
                            from selenium.webdriver.chrome.options import Options
                            
                            chrome_options = Options()
                            chrome_options.add_argument("--headless")
                            driver = webdriver.Chrome(options=chrome_options)
                            

                            from selenium import webdriver
                            from selenium.webdriver.chrome.options import Options
                            
                            chrome_options = Options()
                            chrome_options.add_argument('--proxy-server=http://proxyserver:port')
                            driver = webdriver.Chrome(options=chrome_options)
                            

                            from selenium import webdriver
                            from selenium.webdriver.chrome.options import Options
                            
                            chrome_options = Options()
                            prefs = {"profile.managed_default_content_settings.images": 2}
                            chrome_options.add_experimental_option("prefs", prefs)
                            driver = webdriver.Chrome(options=chrome_options)
                            

                            Selenium提供了多种定位元素的方法,每种都有其适用场景:

                            from selenium import webdriver
                            from selenium.webdriver.common.by import By
                            
                            driver = webdriver.Chrome()
                            driver.get("https://www.example.com")
                            
                            # 1. 通过ID定位(最推荐,高效且唯一)
                            element = driver.find_element(By.ID, "login-button")
                            
                            # 2. 通过Name属性定位
                            element = driver.find_element(By.NAME, "username")
                            
                            # 3. 通过Class Name定位(不唯一时返回第一个匹配元素)
                            element = driver.find_element(By.CLASS_NAME, "login-form")
                            
                            # 4. 通过Tag Name定位
                            element = driver.find_element(By.TAG_NAME, "button")
                            
                            # 5. 通过Link Text定位(完全匹配)
                            element = driver.find_element(By.LINK_TEXT, "Forgot Password?")
                            
                            # 6. 通过Partial Link Text定位(部分匹配)
                            element = driver.find_element(By.PARTIAL_LINK_TEXT, "Forgot")
                            
                            # 7. 通过CSS选择器定位(强大且灵活)
                            element = driver.find_element(By.CSS_SELECTOR, "#login-form .submit-button")
                            
                            # 8. 通过XPath定位(最强大但可能较慢)
                            element = driver.find_element(By.XPATH, "//div[@id='login-form']//button")
                            

                            # 绝对路径(从根节点开始)
                            element = driver.find_element(By.XPATH, "/html/body/div/form/input")
                            
                            # 相对路径(从任意节点开始)
                            element = driver.find_element(By.XPATH, "//input[@name='username']")
                            
                            # 使用contains()函数
                            element = driver.find_element(By.XPATH, "//button[contains(@class, 'login')]")
                            
                            # 使用text()函数
                            element = driver.find_element(By.XPATH, "//a[text()='Forgot Password?']")
                            element = driver.find_element(By.XPATH, "//a[contains(text(), 'Forgot')]")
                            
                            # 使用AND和OR操作符
                            element = driver.find_element(By.XPATH, "//input[@type='text' and @name='username']")
                            element = driver.find_element(By.XPATH, "//button[@type='submit' or @type='button']")
                            
                            # 通过父子关系定位
                            element = driver.find_element(By.XPATH, "//form[@id='login-form']/input")
                            parent = driver.find_element(By.XPATH, "//input[@id='username']/..")
                            
                            # 通过兄弟关系定位
                            element = driver.find_element(By.XPATH, "//input[@id='username']/following-sibling::input")
                            element = driver.find_element(By.XPATH, "//input[@id='password']/preceding-sibling::input")
                            
                            # 按索引定位
                            element = driver.find_element(By.XPATH, "(//input[@type='text'])[2]")
                            
                            # 使用轴(axes)
                            element = driver.find_element(By.XPATH, "//input[@id='username']/ancestor::form")
                            element = driver.find_element(By.XPATH, "//form/descendant::input")
                            

                            # 基本选择器
                            element = driver.find_element(By.CSS_SELECTOR, "#login-button")  # ID选择器
                            element = driver.find_element(By.CSS_SELECTOR, ".login-form")    # Class选择器
                            element = driver.find_element(By.CSS_SELECTOR, "input")          # 标签选择器
                            
                            # 属性选择器
                            element = driver.find_element(By.CSS_SELECTOR, "input[name='username']")
                            element = driver.find_element(By.CSS_SELECTOR, "input[name^='user']")  # 以user开头
                            element = driver.find_element(By.CSS_SELECTOR, "input[name$='name']")  # 以name结尾
                            element = driver.find_element(By.CSS_SELECTOR, "input[name*='erna']")  # 包含erna
                            
                            # 组合选择器
                            element = driver.find_element(By.CSS_SELECTOR, "form input[type='text']")
                            element = driver.find_element(By.CSS_SELECTOR, "form > input")  # 直接子元素
                            element = driver.find_element(By.CSS_SELECTOR, "label + input")  # 紧邻兄弟元素
                            element = driver.find_element(By.CSS_SELECTOR, "label ~ input")  # 通用兄弟元素
                            
                            # 伪类选择器
                            element = driver.find_element(By.CSS_SELECTOR, "input:first-child")
                            element = driver.find_element(By.CSS_SELECTOR, "input:last-child")
                            element = driver.find_element(By.CSS_SELECTOR, "input:nth-child(2)")
                            

                            from selenium.webdriver.support.relative_locator import locate_with
                            
                            # 获取参考元素
                            username_field = driver.find_element(By.ID, "username")
                            
                            # 使用相对定位
                            password_field = driver.find_element(locate_with(By.TAG_NAME, "input").below(username_field))
                            login_button = driver.find_element(locate_with(By.TAG_NAME, "button").below(password_field))
                            remember_me = driver.find_element(locate_with(By.TAG_NAME, "input").to_right_of(password_field))
                            forgot_password = driver.find_element(locate_with(By.TAG_NAME, "a").above(login_button))
                            

                            # 查找所有符合条件的元素
                            elements = driver.find_elements(By.CSS_SELECTOR, ".product-item")
                            
                            # 遍历元素列表
                            for element in elements:
                                name = element.find_element(By.CLASS_NAME, "product-name").text
                                price = element.find_element(By.CLASS_NAME, "product-price").text
                                print(f"产品名称: {name}, 价格: {price}")
                            

                            # 输入操作
                            element.send_keys("test@example.com")  # 输入文本
                            element.send_keys(Keys.CONTROL, 'a')   # 键盘组合键(全选)
                            element.send_keys(Keys.BACK_SPACE)     # 退格键
                            
                            # 点击操作
                            element.click()                        # 点击元素
                            element.submit()                       # 提交表单(适用于表单元素内)
                            
                            # 清除操作
                            element.clear()                        # 清除文本输入框
                            
                            # 获取元素属性和状态
                            value = element.get_attribute("value")  # 获取属性值
                            text = element.text                     # 获取元素文本内容
                            tag = element.tag_name                  # 获取标签名
                            size = element.size                     # 获取元素大小
                            location = element.location             # 获取元素位置
                            is_enabled = element.is_enabled()       # 元素是否启用
                            is_selected = element.is_selected()     # 元素是否选中(复选框、单选按钮等)
                            is_displayed = element.is_displayed()   # 元素是否可见
                            
                            # 特殊元素操作
                            # 下拉菜单
                            from selenium.webdriver.support.select import Select
                            select = Select(driver.find_element(By.ID, "dropdown"))
                            select.select_by_visible_text("Option 1")  # 通过文本选择
                            select.select_by_value("option1")         # 通过值选择
                            select.select_by_index(1)                 # 通过索引选择
                            options = select.options                  # 获取所有选项
                            first_option = select.first_selected_option  # 获取当前选中选项
                            select.deselect_all()                      # 取消所有选择(多选下拉框)
                            
                            # 复选框和单选按钮
                            checkbox = driver.find_element(By.ID, "checkbox")
                            ifnot checkbox.is_selected():
                                checkbox.click()
                            

                            性能优化顺序:ID > Name > CSS > XPath

                            避免使用

                            • 绝对XPath路径(容易失效)
                            • 基于视觉位置的选择器
                            • 多级嵌套CSS选择器

                            推荐使用

                            • 有意义的ID和名称属性
                            • 数据测试属性(如data-testid)
                            • 短而明确的CSS选择器

                            建议添加

                            • 页面加载和元素的等待机制
                            • 查找元素的超时和重试机制
                            • 详细的错误处理机制

                            在Web自动化中,页面加载和元素渲染需要时间,等待机制至关重要。

                            # 设置隐式等待时间(全局设置)
                            driver.implicitly_wait(10)  # 等待最多10秒直到元素出现
                            

                            隐式等待会在查找元素时自动等待一段时间直到元素出现,如果在指定时间内未找到元素,则抛出异常。

                            from selenium.webdriver.support.ui import WebDriverWait
                            from selenium.webdriver.support import expected_conditions as EC
                            
                            # 等待元素可见
                            element = WebDriverWait(driver, 10).until(
                                EC.visibility_of_element_located((By.ID, "element_id"))
                            )
                            
                            # 等待元素可点击
                            element = WebDriverWait(driver, 10).until(
                                EC.element_to_be_clickable((By.ID, "button_id"))
                            )
                            
                            # 等待页面标题包含特定文本
                            WebDriverWait(driver, 10).until(
                                EC.title_contains("Home Page")
                            )
                            
                            # 等待元素消失
                            WebDriverWait(driver, 10).until(
                                EC.invisibility_of_element_located((By.CLASS_NAME, "loading"))
                            )
                            
                            # 等待警告框出现
                            WebDriverWait(driver, 10).until(
                                EC.alert_is_present()
                            )
                            
                            # 等待元素的文本内容满足条件
                            WebDriverWait(driver, 10).until(
                                EC.text_to_be_present_in_element((By.ID, "status"), "Success")
                            )
                            
                            # 等待元素的属性值满足条件
                            WebDriverWait(driver, 10).until(
                                EC.text_to_be_present_in_element_attribute((By.ID, "input"), "value", "text")
                            )
                            

                            from selenium.webdriver.support.ui import WebDriverWait
                            
                            # 自定义等待条件
                            def element_has_class(element, class_name):
                                return class_name in element.get_attribute("class").split()
                            
                            # 使用自定义等待条件
                            element = driver.find_element(By.ID, "myElement")
                            WebDriverWait(driver, 10).until(lambda driver: element_has_class(element, "active"))
                            

                            from selenium.webdriver.support.ui import WebDriverWait
                            from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException
                            
                            # 创建FluentWait实例
                            wait = WebDriverWait(
                                driver,
                                timeout=30,
                                poll_frequency=2,  # 每2秒检查一次
                                ignored_exceptions=[NoSuchElementException, StaleElementReferenceException]
                            )
                            
                            # 使用FluentWait
                            element = wait.until(EC.element_to_be_clickable((By.ID, "myElement")))
                            

                            Selenium操作可能会触发各种异常,合理的异常处理可以提高脚本的健壮性。

                            from selenium.common.exceptions import (
                                NoSuchElementException,  # 元素未找到
                                TimeoutException,        # 等待超时
                                ElementNotVisibleException,  # 元素不可见
                                ElementNotInteractableException,  # 元素不可交互
                                StaleElementReferenceException,  # 元素已过时(DOM已更新)
                                WebDriverException,      # WebDriver通用异常
                                InvalidSelectorException,  # 无效的选择器
                                UnexpectedAlertPresentException,  # 意外的警告框
                                NoAlertPresentException,  # 没有警告框
                                SessionNotCreatedException,  # 会话创建失败
                                ElementClickInterceptedException  # 元素点击被拦截
                            )
                            

                            try:
                                element = driver.find_element(By.ID, "non_existent_element")
                                element.click()
                            except NoSuchElementException:
                                print("元素未找到")
                            except ElementNotInteractableException:
                                print("元素不可交互")
                            except Exception as e:
                                print(f"发生其他异常: {e}")
                            

                            def retry_click(driver, by, value, max_attempts=3, wait_time=1):
                                """
                                尝试多次点击元素
                                """
                                from time import sleep
                                
                                for attempt in range(max_attempts):
                                    try:
                                        element = driver.find_element(by, value)
                                        element.click()
                                        returnTrue
                                    except (NoSuchElementException, ElementNotInteractableException, 
                                            ElementClickInterceptedException, StaleElementReferenceException) as e:
                                        if attempt == max_attempts - 1:
                                            print(f"无法点击元素,错误: {e}")
                                            returnFalse
                                        sleep(wait_time)
                                returnFalse
                            

                            def get_fresh_element(driver, by, value):
                                """
                                获取一个新鲜的元素引用,避免StaleElementReferenceException
                                """
                                try:
                                    return driver.find_element(by, value)
                                except StaleElementReferenceException:
                                    # 重新查找元素
                                    return driver.find_element(by, value)
                            

                            import functools
                            from time import sleep
                            
                            def retry(max_attempts=3, wait_time=1):
                                """
                                函数重试装饰器
                                """
                                def decorator(func):
                                    @functools.wraps(func)
                                    def wrapper(*args, **kwargs):
                                        for attempt in range(max_attempts):
                                            try:
                                                return func(*args, **kwargs)
                                            except (NoSuchElementException, ElementNotInteractableException, 
                                                    StaleElementReferenceException) as e:
                                                if attempt == max_attempts - 1:
                                                    raise e
                                                sleep(wait_time)
                                    return wrapper
                                return decorator
                            
                            # 使用装饰器
                            @retry(max_attempts=5, wait_time=2)
                            def click_element(driver, by, value):
                                driver.find_element(by, value).click()
                            

                            • 避免使用time.sleep()不灵活且低效
                            • 优先使用显式等待:更精确,可控性更强
                            • 结合使用隐式等待和显式等待:隐式等待作为全局保护,显式等待针对特定场景
                            • 设置合理的超时时间:不要过长或过短
                            • 捕获并处理超时异常:提供适当的恢复机制或用户友好的错误信息
                            • 为不同网络环境调整等待策略:可配置的超时参数

                            页面对象模型是一种设计模式,将页面的元素和操作封装在类中,使测试代码更加清晰和可维护。

                            class BasePage:
                                """
                                所有页面的基类
                                """
                                def __init__(self, driver):
                                    self.driver = driver
                                
                                def find_element(self, locator):
                                    return self.driver.find_element(*locator)
                                
                                def find_elements(self, locator):
                                    return self.driver.find_elements(*locator)
                                
                                def click(self, locator):
                                    self.find_element(locator).click()
                                
                                def input_text(self, locator, text):
                                    element = self.find_element(locator)
                                    element.clear()
                                    element.send_keys(text)
                                
                                def get_text(self, locator):
                                    return self.find_element(locator).text
                                
                                def is_element_present(self, locator):
                                    try:
                                        self.find_element(locator)
                                        returnTrue
                                    except NoSuchElementException:
                                        returnFalse
                                
                                def wait_for_element(self, locator, timeout=10):
                                    try:
                                        WebDriverWait(self.driver, timeout).until(
                                            EC.presence_of_element_located(locator)
                                        )
                                        returnTrue
                                    except TimeoutException:
                                        returnFalse
                            
                            
                            class LoginPage(BasePage):
                                """
                                登录页面对象
                                """
                                # 页面元素定位
                                _username_field = (By.ID, "username")
                                _password_field = (By.ID, "password")
                                _login_button = (By.ID, "login_button")
                                _error_message = (By.CLASS_NAME, "error-message")
                                
                                def __init__(self, driver):
                                    super().__init__(driver)
                                    self.driver.get("https://example.com/login")
                                
                                def enter_username(self, username):
                                    self.input_text(self._username_field, username)
                                    return self
                                
                                def enter_password(self, password):
                                    self.input_text(self._password_field, password)
                                    return self
                                
                                def click_login(self):
                                    self.click(self._login_button)
                                    # 根据登录结果返回不同的页面对象
                                    if"dashboard"in self.driver.current_url:
                                        return DashboardPage(self.driver)
                                    return self
                                
                                def login(self, username, password):
                                    self.enter_username(username)
                                    self.enter_password(password)
                                    return self.click_login()
                                
                                def get_error_message(self):
                                    if self.is_element_present(self._error_message):
                                        return self.get_text(self._error_message)
                                    return""
                            
                            
                            class DashboardPage(BasePage):
                                """
                                仪表盘页面对象
                                """
                                _welcome_message = (By.ID, "welcome")
                                _logout_button = (By.ID, "logout")
                                
                                def is_loaded(self):
                                    return self.wait_for_element(self._welcome_message)
                                
                                def get_welcome_message(self):
                                    return self.get_text(self._welcome_message)
                                
                                def logout(self):
                                    self.click(self._logout_button)
                                    return LoginPage(self.driver)
                            

                            def test_login_success():
                                driver = webdriver.Chrome()
                                try:
                                    login_page = LoginPage(driver)
                                    dashboard_page = login_page.login("valid_user", "valid_password")
                                    
                                    assert dashboard_page.is_loaded()
                                    assert"Welcome"in dashboard_page.get_welcome_message()
                                finally:
                                    driver.quit()
                            
                            def test_login_failure():
                                driver = webdriver.Chrome()
                                try:
                                    login_page = LoginPage(driver)
                                    result_page = login_page.login("invalid_user", "invalid_password")
                                    
                                    assert isinstance(result_page, LoginPage)
                                    assert"Invalid credentials"in result_page.get_error_message()
                                finally:
                                    driver.quit()
                            

                            import unittest
                            from selenium import webdriver
                            from selenium.webdriver.chrome.service import Service
                            from webdriver_manager.chrome import ChromeDriverManager
                            
                            class TestLogin(unittest.TestCase):
                                def setUp(self):
                                    self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
                                    self.driver.maximize_window()
                                    self.login_page = LoginPage(self.driver)
                                
                                def tearDown(self):
                                    self.driver.quit()
                                
                                def test_valid_login(self):
                                    dashboard_page = self.login_page.login("valid_user", "valid_password")
                                    self.assertTrue(dashboard_page.is_loaded())
                                    self.assertIn("Welcome", dashboard_page.get_welcome_message())
                                
                                def test_invalid_login(self):
                                    result_page = self.login_page.login("invalid_user", "invalid_password")
                                    self.assertIsInstance(result_page, LoginPage)
                                    self.assertIn("Invalid credentials", result_page.get_error_message())
                            
                            if __name__ == "__main__":
                                unittest.main()
                            

                            import pytest
                            from selenium import webdriver
                            from selenium.webdriver.chrome.service import Service
                            from webdriver_manager.chrome import ChromeDriverManager
                            
                            @pytest.fixture
                            def driver():
                                # 设置
                                driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
                                driver.maximize_window()
                                yield driver
                                # 清理
                                driver.quit()
                            
                            @pytest.fixture
                            def login_page(driver):
                                return LoginPage(driver)
                            
                            def test_valid_login(login_page):
                                dashboard_page = login_page.login("valid_user", "valid_password")
                                assert dashboard_page.is_loaded()
                                assert"Welcome"in dashboard_page.get_welcome_message()
                            
                            def test_invalid_login(login_page):
                                result_page = login_page.login("invalid_user", "invalid_password")
                                assert isinstance(result_page, LoginPage)
                                assert"Invalid credentials"in result_page.get_error_message()
                            

                            # features/login.feature
                            Feature: User Login
                              As a user
                              I want to be able to login to the application
                              So that I can access my account
                            
                              Scenario: Successful login with valid credentials
                                Given the user is on the login page
                                When the user enters "valid_user"as username
                                And the user enters "valid_password"as password
                                And the user clicks the login button
                                Then the user should be redirected to the dashboard
                                And the dashboard should display a welcome message
                            
                              Scenario: Failed login with invalid credentials
                                Given the user is on the login page
                                When the user enters "invalid_user"as username
                                And the user enters "invalid_password"as password
                                And the user clicks the login button
                                Then the user should remain on the login page
                                And an error message should be displayed
                            
                            # steps/login_steps.py
                            from behave import given, when, then
                            from pages.login_page import LoginPage
                            from pages.dashboard_page import DashboardPage
                            
                            @given('the user is on the login page')
                            def step_impl(context):
                                context.login_page = LoginPage(context.driver)
                            
                            @when('the user enters "{username}" as username')
                            def step_impl(context, username):
                                context.login_page.enter_username(username)
                            
                            @when('the user enters "{password}" as password')
                            def step_impl(context, password):
                                context.login_page.enter_password(password)
                            
                            @when('the user clicks the login button')
                            def step_impl(context):
                                context.result_page = context.login_page.click_login()
                            
                            @then('the user should be redirected to the dashboard')
                            def step_impl(context):
                                assert isinstance(context.result_page, DashboardPage)
                            
                            @then('the dashboard should display a welcome message')
                            def step_impl(context):
                                assert"Welcome"in context.result_page.get_welcome_message()
                            
                            @then('the user should remain on the login page')
                            def step_impl(context):
                                assert isinstance(context.result_page, LoginPage)
                            
                            @then('an error message should be displayed')
                            def step_impl(context):
                                assert"Invalid credentials"in context.result_page.get_error_message()
                            

                            class PageFactory:
                                """
                                页面对象工厂类
                                """
                                @staticmethod
                                def get_page(page_name, driver):
                                    pages = {
                                        "login": LoginPage,
                                        "dashboard": DashboardPage,
                                        "profile": ProfilePage,
                                        "settings": SettingsPage
                                    }
                                    
                                    if page_name.lower() notin pages:
                                        raise ValueError(f"不支持的页面: {page_name}")
                                    
                                    return pages[page_name.lower()](driver)
                            

                            class WebDriverManager:
                                """
                                WebDriver管理器(单例模式)
                                """
                                _instance = None
                                
                                def __new__(cls):
                                    if cls._instance isNone:
                                        cls._instance = super(WebDriverManager, cls).__new__(cls)
                                        cls._instance.driver = None
                                    return cls._instance
                                
                                def get_driver(self, browser="chrome"):
                                    if self.driver isNone:
                                        if browser.lower() == "chrome":
                                            self.driver = webdriver.Chrome()
                                        elif browser.lower() == "firefox":
                                            self.driver = webdriver.Firefox()
                                        else:
                                            raise ValueError(f"不支持的浏览器: {browser}")
                                        
                                        self.driver.maximize_window()
                                        self.driver.implicitly_wait(10)
                                    
                                    return self.driver
                                
                                def quit(self):
                                    if self.driver:
                                        self.driver.quit()
                                        self.driver = None
                            

                            from abc import ABC, abstractmethod
                            
                            class WaitStrategy(ABC):
                                """
                                等待策略基类
                                """
                                @abstractmethod
                                def wait_for(self, driver, locator):
                                    pass
                            
                            class VisibilityStrategy(WaitStrategy):
                                """
                                等待元素可见策略
                                """
                                def wait_for(self, driver, locator, timeout=10):
                                    return WebDriverWait(driver, timeout).until(
                                        EC.visibility_of_element_located(locator)
                                    )
                            
                            class ClickableStrategy(WaitStrategy):
                                """
                                等待元素可点击策略
                                """
                                def wait_for(self, driver, locator, timeout=10):
                                    return WebDriverWait(driver, timeout).until(
                                        EC.element_to_be_clickable(locator)
                                    )
                            
                            class PresenceStrategy(WaitStrategy):
                                """
                                等待元素存在策略
                                """
                                def wait_for(self, driver, locator, timeout=10):
                                    return WebDriverWait(driver, timeout).until(
                                        EC.presence_of_element_located(locator)
                                    )
                            
                            # 使用策略模式的高级页面基类
                            class AdvancedBasePage:
                                def __init__(self, driver):
                                    self.driver = driver
                                    self.wait_strategies = {
                                        "visible": VisibilityStrategy(),
                                        "clickable": ClickableStrategy(),
                                        "present": PresenceStrategy()
                                    }
                                
                                def find_element(self, locator, strategy="present"):
                                    return self.wait_strategies[strategy].wait_for(self.driver, locator)
                            

                            import json
                            import os
                            
                            class ConfigManager:
                                """
                                配置管理器
                                """
                                _instance = None
                                
                                def __new__(cls):
                                    if cls._instance isNone:
                                        cls._instance = super(ConfigManager, cls).__new__(cls)
                                        cls._instance.config = {}
                                        cls._instance.load_config()
                                    return cls._instance
                                
                                def load_config(self, config_file="config.json"):
                                    if os.path.exists(config_file):
                                        with open(config_file, "r") as f:
                                            self.config = json.load(f)
                                    else:
                                        # 默认配置
                                        self.config = {
                                            "browser": "chrome",
                                            "implicit_wait": 10,
                                            "explicit_wait": 20,
                                            "base_url": "https://example.com",
                                            "headless": False,
                                            "screenshots_dir": "screenshots",
                                            "logs_dir": "logs"
                                        }
                                
                                def get(self, key, default=None):
                                    return self.config.get(key, default)
                            

                            import logging
                            import os
                            from datetime import datetime
                            
                            class LogManager:
                                """
                                日志管理器
                                """
                                _instance = None
                                
                                def __new__(cls):
                                    if cls._instance isNone:
                                        cls._instance = super(LogManager, cls).__new__(cls)
                                        cls._instance.setup_logger()
                                    return cls._instance
                                
                                def setup_logger(self):
                                    config = ConfigManager().get("logs", {})
                                    logs_dir = config.get("dir", "logs")
                                    log_level = config.get("level", "INFO")
                                    
                                    ifnot os.path.exists(logs_dir):
                                        os.makedirs(logs_dir)
                                    
                                    log_file = os.path.join(logs_dir, f"test_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log")
                                    
                                    # 设置日志级别映射
                                    level_map = {
                                        "DEBUG": logging.DEBUG,
                                        "INFO": logging.INFO,
                                        "WARNING": logging.WARNING,
                                        "ERROR": logging.ERROR,
                                        "CRITICAL": logging.CRITICAL
                                    }
                                    
                                    # 设置根日志记录器
                                    self.logger = logging.getLogger("selenium_framework")
                                    self.logger.setLevel(level_map.get(log_level.upper(), logging.INFO))
                                    
                                    # 文件处理器
                                    file_handler = logging.FileHandler(log_file)
                                    file_handler.setLevel(level_map.get(log_level.upper(), logging.INFO))
                                    
                                    # 控制台处理器
                                    console_handler = logging.StreamHandler()
                                    console_handler.setLevel(level_map.get(log_level.upper(), logging.INFO))
                                    
                                    # 日志格式
                                    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
                                    file_handler.setFormatter(formatter)
                                    console_handler.setFormatter(formatter)
                                    
                                    # 添加处理器
                                    self.logger.addHandler(file_handler)
                                    self.logger.addHandler(console_handler)
                                
                                def get_logger(self):
                                    return self.logger
                            

                            from selenium.webdriver.common.action_chains import ActionChains
                            from selenium.webdriver.common.keys import Keys
                            
                            # 基本鼠标操作
                            def perform_hover(driver, element):
                                """执行悬停操作"""
                                ActionChains(driver).move_to_element(element).perform()
                            
                            def perform_right_click(driver, element):
                                """执行右键点击操作"""
                                ActionChains(driver).context_click(element).perform()
                            
                            def perform_double_click(driver, element):
                                """执行双击操作"""
                                ActionChains(driver).double_click(element).perform()
                            
                            def perform_drag_and_drop(driver, source_element, target_element):
                                """执行拖放操作"""
                                ActionChains(driver).drag_and_drop(source_element, target_element).perform()
                            
                            def perform_drag_and_drop_by_offset(driver, element, x_offset, y_offset):
                                """执行偏移拖放操作"""
                                ActionChains(driver).drag_and_drop_by_offset(element, x_offset, y_offset).perform()
                            
                            # 组合键盘操作
                            def perform_ctrl_click(driver, element):
                                """执行Ctrl+点击操作(多选)"""
                                ActionChains(driver).key_down(Keys.CONTROL).click(element).key_up(Keys.CONTROL).perform()
                            
                            def perform_shift_click(driver, element):
                                """执行Shift+点击操作(范围选择)"""
                                ActionChains(driver).key_down(Keys.SHIFT).click(element).key_up(Keys.SHIFT).perform()
                            
                            def perform_select_all(driver):
                                """执行全选操作(Ctrl+A)"""
                                ActionChains(driver).key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform()
                            
                            def perform_copy(driver):
                                """执行复制操作(Ctrl+C)"""
                                ActionChains(driver).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()
                            
                            def perform_paste(driver):
                                """执行粘贴操作(Ctrl+V)"""
                                ActionChains(driver).key_down(Keys.CONTROL).send_keys('v').key_up(Keys.CONTROL).perform()
                            
                            # 链式组合操作
                            def perform_complex_action(driver, element1, element2):
                                """执行复杂组合操作"""
                                ActionChains(driver)
                                    .move_to_element(element1)
                                    .pause(1)  # 暂停1秒
                                    .click()
                                    .move_to_element(element2)
                                    .click()
                                    .perform()
                            

                            def trigger_js_event(driver, element, event_name):
                                """触发JavaScript事件"""
                                js_code = f"arguments[0].dispatchEvent(new Event('{event_name}'));"
                                driver.execute_script(js_code, element)
                            
                            def focus_element(driver, element):
                                """使元素获取焦点"""
                                driver.execute_script("arguments[0].focus();", element)
                            
                            def blur_element(driver, element):
                                """使元素失去焦点"""
                                driver.execute_script("arguments[0].blur();", element)
                            
                            def scroll_to_element(driver, element):
                                """滚动到元素位置"""
                                driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", element)
                            
                            def scroll_to_top(driver):
                                """滚动到页面顶部"""
                                driver.execute_script("window.scrollTo(0, 0);")
                            
                            def scroll_to_bottom(driver):
                                """滚动到页面底部"""
                                driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
                            

                            def switch_to_window_by_title(driver, title):
                                """切换到指定标题的窗口"""
                                current_window = driver.current_window_handle
                                for window in driver.window_handles:
                                    driver.switch_to.window(window)
                                    if title in driver.title:
                                        returnTrue
                                # 如果没有找到匹配标题的窗口,切回原窗口
                                driver.switch_to.window(current_window)
                                returnFalse
                            
                            def switch_to_window_by_url(driver, url_part):
                                """切换到URL包含指定部分的窗口"""
                                current_window = driver.current_window_handle
                                for window in driver.window_handles:
                                    driver.switch_to.window(window)
                                    if url_part in driver.current_url:
                                        returnTrue
                                # 如果没有找到匹配URL的窗口,切回原窗口
                                driver.switch_to.window(current_window)
                                returnFalse
                            
                            def close_all_windows_except_current(driver):
                                """关闭除当前窗口外的所有窗口"""
                                current_window = driver.current_window_handle
                                for window in driver.window_handles:
                                    if window != current_window:
                                        driver.switch_to.window(window)
                                        driver.close()
                                driver.switch_to.window(current_window)
                            
                            def open_new_tab(driver, url=None):
                                """打开新标签页"""
                                driver.execute_script("window.open();")
                                driver.switch_to.window(driver.window_handles[-1])
                                if url:
                                    driver.get(url)
                            
                            def handle_popup_window(driver, action="accept"):
                                """处理弹出窗口"""
                                try:
                                    if action.lower() == "accept":
                                        driver.switch_to.alert.accept()
                                    elif action.lower() == "dismiss":
                                        driver.switch_to.alert.dismiss()
                                    elif action.lower() == "text":
                                        return driver.switch_to.alert.text
                                    else:
                                        raise ValueError(f"不支持的操作: {action}")
                                    returnTrue
                                except:
                                    returnFalse
                            

                            def switch_to_frame_by_index(driver, index):
                                """通过索引切换到iframe"""
                                try:
                                    driver.switch_to.frame(index)
                                    returnTrue
                                except:
                                    returnFalse
                            
                            def switch_to_frame_by_name_or_id(driver, name_or_id):
                                """通过名称或ID切换到iframe"""
                                try:
                                    driver.switch_to.frame(name_or_id)
                                    returnTrue
                                except:
                                    returnFalse
                            
                            def switch_to_frame_by_element(driver, element):
                                """通过元素切换到iframe"""
                                try:
                                    driver.switch_to.frame(element)
                                    returnTrue
                                except:
                                    returnFalse
                            
                            def switch_to_parent_frame(driver):
                                """切换到父iframe"""
                                try:
                                    driver.switch_to.parent_frame()
                                    returnTrue
                                except:
                                    returnFalse
                            
                            def switch_to_default_content(driver):
                                """切换到主文档"""
                                try:
                                    driver.switch_to.default_content()
                                    returnTrue
                                except:
                                    returnFalse
                            
                            def get_iframe_count(driver):
                                """获取页面中iframe的数量"""
                                return len(driver.find_elements(By.TAG_NAME, "iframe"))
                            
                            def execute_in_iframe(driver, iframe_locator, action_func):
                                """在iframe中执行操作"""
                                driver.switch_to.frame(driver.find_element(*iframe_locator))
                                try:
                                    result = action_func(driver)
                                    return result
                                finally:
                                    driver.switch_to.default_content()
                            

                            def upload_file(driver, file_input_locator, file_path):
                                """
                                上传文件(适用于<input type="file">元素)
                                """
                                try:
                                    file_input = driver.find_element(*file_input_locator)
                                    file_input.send_keys(file_path)
                                    returnTrue
                                except Exception as e:
                                    print(f"文件上传失败: {e}")
                                    returnFalse
                            
                            def upload_file_without_input(driver, upload_button_locator, file_path):
                                """
                                上传文件(适用于没有可见<input type="file">的情况)
                                使用JS创建一个隐藏的文件输入元素
                                """
                                try:
                                    # 创建一个隐藏的文件输入元素
                                    js_script = """
                                    const input = document.createElement('input');
                                    input.type = 'file';
                                    input.style.display = 'none';
                                    input.id = 'hidden-file-input';
                                    document.body.appendChild(input);
                                    return input;
                                    """
                                    file_input = driver.execute_script(js_script)
                                    
                                    # 设置文件路径
                                    file_input.send_keys(file_path)
                                    
                                    # 触发上传按钮的点击事件
                                    upload_button = driver.find_element(*upload_button_locator)
                                    driver.execute_script("arguments[0].click();", upload_button)
                                    
                                    # 移除隐藏的文件输入元素
                                    driver.execute_script("document.getElementById('hidden-file-input').remove();")
                                    
                                    returnTrue
                                except Exception as e:
                                    print(f"文件上传失败: {e}")
                                    returnFalse
                            

                            import os
                            import time
                            from pathlib import Path
                            
                            def setup_chrome_download_path(download_dir):
                                """
                                设置Chrome浏览器的下载路径
                                """
                                options = webdriver.ChromeOptions()
                                prefs = {
                                    "download.default_directory": download_dir,
                                    "download.prompt_for_download": False,
                                    "download.directory_upgrade": True,
                                    "safebrowsing.enabled": True
                                }
                                options.add_experimental_option("prefs", prefs)
                                return options
                            
                            def wait_for_download_to_complete(download_dir, timeout=60, check_interval=1):
                                """
                                等待下载完成
                                """
                                start_time = time.time()
                                while time.time() - start_time < timeout:
                                    # 检查是否有部分下载的文件(.crdownload, .part等)
                                    downloading_files = list(Path(download_dir).glob("*.crdownload")) + list(Path(download_dir).glob("*.part"))
                                    ifnot downloading_files:
                                        # 找出最近下载的文件
                                        downloaded_files = list(Path(download_dir).glob("*"))
                                        if downloaded_files:
                                            downloaded_files.sort(key=lambda x: x.stat().st_mtime, reverse=True)
                                            return str(downloaded_files[0])
                                    time.sleep(check_interval)
                                raise TimeoutError("文件下载超时")
                            
                            def download_file(driver, download_button_locator, download_dir, timeout=60):
                                """
                                下载文件
                                """
                                try:
                                    # 确保下载目录存在
                                    os.makedirs(download_dir, exist_ok=True)
                                    
                                    # 点击下载按钮
                                    download_button = driver.find_element(*download_button_locator)
                                    download_button.click()
                                    
                                    # 等待下载完成
                                    downloaded_file = wait_for_download_to_complete(download_dir, timeout)
                                    return downloaded_file
                                except Exception as e:
                                    print(f"文件下载失败: {e}")
                                    returnNone
                            

                            import os
                            import time
                            from datetime import datetime
                            
                            def take_screenshot(driver, directory="screenshots", filename=None):
                                """
                                截取屏幕截图
                                """
                                try:
                                    # 确保目录存在
                                    os.makedirs(directory, exist_ok=True)
                                    
                                    # 如果未指定文件名,使用时间戳生成
                                    ifnot filename:
                                        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                                        filename = f"screenshot_{timestamp}.png"
                                    
                                    # 拼接完整路径
                                    file_path = os.path.join(directory, filename)
                                    
                                    # 截图
                                    driver.save_screenshot(file_path)
                                    return file_path
                                except Exception as e:
                                    print(f"截图失败: {e}")
                                    returnNone
                            
                            def take_element_screenshot(driver, element, directory="screenshots", filename=None):
                                """
                                截取元素截图
                                """
                                try:
                                    # 确保目录存在
                                    os.makedirs(directory, exist_ok=True)
                                    
                                    # 如果未指定文件名,使用时间戳生成
                                    ifnot filename:
                                        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                                        filename = f"element_screenshot_{timestamp}.png"
                                    
                                    # 拼接完整路径
                                    file_path = os.path.join(directory, filename)
                                    
                                    # 截取元素截图
                                    element.screenshot(file_path)
                                    return file_path
                                except Exception as e:
                                    print(f"元素截图失败: {e}")
                                    returnNone
                            
                            def screenshot_on_failure(func):
                                """
                                失败时自动截图的装饰器
                                """
                                def wrapper(*args, **kwargs):
                                    try:
                                        return func(*args, **kwargs)
                                    except Exception as e:
                                        # 假设第一个参数是self,第二个参数是driver
                                        driver = args[1] if len(args) > 1elseNone
                                        if driver:
                                            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                                            filename = f"failure_{func.__name__}_{timestamp}.png"
                                            take_screenshot(driver, filename=filename)
                                        raise e
                                return wrapper
                            

                            def verify_element_text(driver, locator, expected_text, contains=False):
                                """
                                验证元素文本
                                """
                                try:
                                    element = driver.find_element(*locator)
                                    actual_text = element.text
                                    if contains:
                                        assert expected_text in actual_text, f"期望文本包含'{expected_text}',实际文本为'{actual_text}'"
                                    else:
                                        assert actual_text == expected_text, f"期望文本为'{expected_text}',实际文本为'{actual_text}'"
                                    returnTrue
                                except AssertionError as e:
                                    print(f"验证失败: {e}")
                                    returnFalse
                            
                            def verify_element_attribute(driver, locator, attribute, expected_value, contains=False):
                                """
                                验证元素属性
                                """
                                try:
                                    element = driver.find_element(*locator)
                                    actual_value = element.get_attribute(attribute)
                                    if contains:
                                        assert expected_value in actual_value, f"期望属性'{attribute}'包含'{expected_value}',实际值为'{actual_value}'"
                                    else:
                                        assert actual_value == expected_value, f"期望属性'{attribute}'为'{expected_value}',实际值为'{actual_value}'"
                                    returnTrue
                                except AssertionError as e:
                                    print(f"验证失败: {e}")
                                    returnFalse
                            
                            def verify_element_visible(driver, locator, timeout=10):
                                """
                                验证元素可见
                                """
                                try:
                                    WebDriverWait(driver, timeout).until(EC.visibility_of_element_located(locator))
                                    returnTrue
                                except TimeoutException:
                                    print(f"元素在{timeout}秒内未可见: {locator}")
                                    returnFalse
                            
                            def verify_element_not_visible(driver, locator, timeout=10):
                                """
                                验证元素不可见
                                """
                                try:
                                    WebDriverWait(driver, timeout).until(EC.invisibility_of_element_located(locator))
                                    returnTrue
                                except TimeoutException:
                                    print(f"元素在{timeout}秒内仍然可见: {locator}")
                                    returnFalse
                            
                            def verify_url(driver, expected_url, contains=False, timeout=10):
                                """
                                验证URL
                                """
                                try:
                                    if contains:
                                        WebDriverWait(driver, timeout).until(lambda d: expected_url in d.current_url)
                                    else:
                                        WebDriverWait(driver, timeout).until(lambda d: d.current_url == expected_url)
                                    returnTrue
                                except TimeoutException:
                                    print(f"URL验证失败,期望URL{'' if contains else '为'}{expected_url},实际URL为{driver.current_url}")
                                    returnFalse
                            
                            def verify_title(driver, expected_title, contains=False, timeout=10):
                                """
                                验证页面标题
                                """
                                try:
                                    if contains:
                                        WebDriverWait(driver, timeout).until(lambda d: expected_title in d.title)
                                    else:
                                        WebDriverWait(driver, timeout).until(lambda d: d.title == expected_title)
                                    returnTrue
                                except TimeoutException:
                                    print(f"标题验证失败,期望标题{'' if contains else '为'}{expected_title},实际标题为{driver.title}")
                                    returnFalse
                            

                            def measure_page_load_time(driver, url):
                                """
                                测量页面加载时间
                                """
                                start_time = time.time()
                                driver.get(url)
                                
                                # 等待页面完全加载
                                WebDriverWait(driver, 60).until(
                                    lambda d: d.execute_script("return document.readyState") == "complete"
                                )
                                
                                end_time = time.time()
                                load_time = end_time - start_time
                                
                                return load_time
                            

                            def get_performance_metrics(driver):
                                """
                                获取浏览器性能指标
                                """
                                # 使用Navigation Timing API
                                navigation_timing = driver.execute_script("""
                                    var performance = window.performance;
                                    var timingObj = performance.timing;
                                    var loadTime = timingObj.loadEventEnd - timingObj.navigationStart;
                                    var dnsTime = timingObj.domainLookupEnd - timingObj.domainLookupStart;
                                    var tcpTime = timingObj.connectEnd - timingObj.connectStart;
                                    var serverTime = timingObj.responseEnd - timingObj.requestStart;
                                    var domTime = timingObj.domComplete - timingObj.domLoading;
                                    
                                    return {
                                        'loadTime': loadTime,
                                        'dnsTime': dnsTime,
                                        'tcpTime': tcpTime,
                                        'serverTime': serverTime,
                                        'domTime': domTime,
                                        'firstPaint': timingObj.responseStart - timingObj.navigationStart,
                                        'ttfb': timingObj.responseStart - timingObj.requestStart
                                    };
                                """)
                                
                                return navigation_timing
                            
                            def get_resource_timing(driver):
                                """
                                获取资源加载时间
                                """
                                resources = driver.execute_script("""
                                    var resources = window.performance.getEntriesByType('resource');
                                    return resources.map(function(resource) {
                                        return {
                                            'name': resource.name,
                                            'startTime': resource.startTime,
                                            'duration': resource.duration,
                                            'initiatorType': resource.initiatorType,
                                            'size': resource.transferSize
                                        };
                                    });
                                """)
                                
                                return resources
                            

                            def optimize_chrome_for_performance():
                                """
                                优化Chrome浏览器以提高性能
                                """
                                options = webdriver.ChromeOptions()
                                
                                # 禁用不必要的浏览器功能
                                options.add_argument("--disable-extensions")
                                options.add_argument("--disable-gpu")
                                options.add_argument("--disable-dev-shm-usage")
                                options.add_argument("--disable-browser-side-navigation")
                                options.add_argument("--disable-infobars")
                                options.add_argument("--disable-notifications")
                                options.add_argument("--disable-popup-blocking")
                                
                                # 减少内存使用
                                options.add_argument("--disable-features=site-per-process")
                                options.add_argument("--process-per-site")
                                
                                # 禁用图片加载以提高速度
                                prefs = {
                                    "profile.managed_default_content_settings.images": 2,
                                    "profile.default_content_setting_values.notifications": 2,
                                    "profile.default_content_setting_values.geolocation": 2
                                }
                                options.add_experimental_option("prefs", prefs)
                                
                                # 使用无头模式
                                options.add_argument("--headless")
                                
                                return options
                            

                            获取浏览器控制台日志

                            def get_browser_logs(driver):
                                """
                                获取浏览器控制台日志
                                """
                                logs = driver.get_log('browser')
                                return logs
                            
                            def print_browser_logs(driver):
                                """
                                打印浏览器控制台日志
                                """
                                logs = driver.get_log('browser')
                                for log in logs:
                                    print(f"[{log['level']}] {log['message']}")

                            以上就是从入门到精通介绍Python中Selenium安装使用的完整指南的详细内容,更多关于Python Selenium的资料请关注风君子博客其它相关文章!

                            您可能感兴趣的文章:

                            • Python Selenium打开指定路径浏览器的几种实现方法
                            • python中selenium安装配置与使用示例
                            • Python使用Selenium检查元素是否存在的方法
                            • Python使用Selenium进行Web自动化的全过程
                            • python selenium如何防止被浏览器检测
                            • Python利用Selenium进行网页自动化与动态内容抓取操作
                            • Python+Selenium实现无头浏览器网页截图

                            站内搜索