云计算百科
云计算领域专业知识百科平台

全面了解selenium

引言:为什么选择 Selenium?

在当今的互联网时代,Web 应用已经成为企业服务用户的主要载体。无论是电商平台、社交媒体还是企业内部系统,都需要保证其功能稳定性和用户体验。这就催生了对 Web 自动化工具的强烈需求 —— 开发者需要高效地测试 Web 应用,数据分析师需要批量获取网页信息,而普通用户也希望通过自动化脚本简化重复操作。

Selenium作为目前最流行的 Web 自动化工具之一,自 2004 年诞生以来,已经成为行业标准。它支持多种编程语言(Python、Java、C# 等)、多种浏览器(Chrome、Firefox、Edge 等)和多种操作系统,能够模拟真实用户的操作行为,实现从简单的表单提交到复杂的单页应用交互的全流程自动化。

本文将从 Selenium 的核心概念出发,通过丰富的代码示例,全面覆盖以下内容:

  • Selenium 的架构与核心组件
  • 环境搭建与基础配置
  • 元素定位与交互操作
  • 高级功能(等待机制、窗口切换、文件处理等)
  • 自动化测试框架集成
  • 网页数据爬取实战
  • 性能优化与最佳实践

无论你是测试工程师、数据分析师还是开发人员,掌握 Selenium 都将显著提升你的工作效率,让你从繁琐的重复劳动中解放出来。

一、Selenium 核心概念与架构

1.1 Selenium 是什么?

Selenium 是一个用于 Web 应用测试的开源工具集,它允许开发者通过编程方式控制浏览器执行各种操作,如点击按钮、填写表单、页面导航等。与其他自动化工具相比,Selenium 的核心优势在于:

  • 真实浏览器环境:直接驱动真实浏览器,模拟用户真实操作,避免了与 JavaScript 渲染相关的兼容性问题
  • 跨平台与跨浏览器:支持 Windows、macOS、Linux,以及 Chrome、Firefox、Safari 等主流浏览器
  • 多语言支持:提供 Python、Java、C#、Ruby 等多种编程语言的 API
  • 强大的社区支持:作为最流行的 Web 自动化工具,拥有丰富的文档和解决方案

1.2 Selenium 的核心组件

Selenium 生态系统包含多个组件,各自承担不同的功能:

  • Selenium WebDriver:核心组件,提供编程接口用于控制浏览器,支持多种编程语言,是本文的重点内容
  • Selenium IDE:浏览器插件,用于录制和回放操作,适合快速创建简单的自动化脚本
  • Selenium Grid:用于分布式测试,允许在不同的机器和浏览器上并行执行测试用例,提高测试效率
  • 1.3 Selenium 的工作原理

    Selenium WebDriver 采用客户端 – 服务器架构:

    • 客户端:开发者编写的自动化脚本(如 Python 代码)
    • 浏览器驱动:特定浏览器的驱动程序(如 ChromeDriver),作为客户端与浏览器之间的桥梁
    • 浏览器:实际执行操作的浏览器(如 Chrome)

    其工作流程如下:

  • 客户端脚本通过 WebDriver API 发送指令(如 "打开网页"、"点击按钮")
  • 浏览器驱动接收指令并将其转换为浏览器能理解的格式
  • 浏览器执行相应操作并将结果返回给驱动
  • 驱动将结果反馈给客户端脚本
  • 这种架构的优势在于:

    • 支持跨语言开发(只需实现对应的 WebDriver API)
    • 可以远程控制不同机器上的浏览器
    • 与浏览器的交互更加稳定可靠

    二、环境搭建与基础配置

    2.1 安装 Python

    Selenium 支持多种编程语言,其中 Python 因其简洁易学的特点成为最受欢迎的选择之一。首先需要安装 Python 环境:

  • 访问 Python 官网(Welcome to Python.org)下载对应操作系统的安装包
  • 安装时勾选 "Add Python to PATH",方便在命令行中直接使用 Python
  • 验证安装:打开命令行,输入python –version或python3 –version,显示版本号即安装成功
  • 2.2 安装 Selenium 库

    使用 pip(Python 包管理工具)安装 Selenium:

    bash

    pip install selenium
    # 或使用pip3(区分Python2和Python3时)
    pip3 install selenium

    验证安装:

    bash

    python -c "import selenium; print(selenium.__version__)"

    若输出 Selenium 版本号(如 4.15.0),则安装成功。

    2.3 安装浏览器驱动

    Selenium 需要特定的浏览器驱动才能控制浏览器,不同浏览器需要对应版本的驱动:

    浏览器驱动下载地址
    Chrome https://sites.google.com/chromium.org/driver/
    Firefox https://github.com/mozilla/geckodriver/releases
    Edge Microsoft Edge WebDriver | Microsoft Edge Developer
    Safari 内置(需在 Safari 设置中启用 "开发" 菜单下的 "允许远程自动化")

    安装步骤(以 Chrome 为例):

  • 查看 Chrome 版本:打开 Chrome,在地址栏输入chrome://version/,记录版本号(如 118.0.5993.88)
  • 下载对应版本的 ChromeDriver:在下载页面找到与 Chrome 版本匹配的驱动(主版本号需一致,如 118.x.x.x)
  • 配置驱动:
    • Windows:将下载的 chromedriver.exe 放入 Python 安装目录(或添加到系统 PATH 环境变量)
    • macOS/Linux:将驱动文件放入 /usr/local/bin/ 目录,或添加到 PATH
  • 验证驱动配置:

    bash

    # Windows
    chromedriver –version

    # macOS/Linux
    chromedriver –version

    若输出驱动版本号,则配置成功。

    2.4 第一个 Selenium 程序

    让我们编写一个简单的程序验证环境是否配置正确:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.chrome.service import Service
    from webdriver_manager.chrome import ChromeDriverManager

    # 初始化Chrome浏览器
    # 使用webdriver_manager自动管理驱动(无需手动下载)
    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

    # 打开百度首页
    driver.get("https://www.baidu.com")

    # 打印页面标题
    print("页面标题:", driver.title)

    # 等待3秒(让我们看清效果)
    import time
    time.sleep(3)

    # 关闭浏览器
    driver.quit()

    代码说明:

    • webdriver.Chrome():创建 Chrome 浏览器实例
    • driver.get(url):打开指定 URL
    • driver.title:获取当前页面标题
    • driver.quit():关闭浏览器并释放资源

    运行程序后,会自动打开 Chrome 浏览器并访问百度首页,控制台输出页面标题,3 秒后关闭浏览器。

    提示:webdriver_manager库可以自动下载和管理浏览器驱动,避免版本匹配问题,安装方法:pip install webdriver-manager

    三、元素定位:Selenium 的核心技能

    在 Web 自动化中,元素定位是最基础也是最重要的操作 —— 我们需要先找到页面上的元素(如按钮、输入框),才能进行后续的交互。Selenium 提供了多种元素定位方法,适用于不同场景。

    3.1 常用元素定位方法

    Selenium 提供了 8 种元素定位方法,定义在By类中:

    方法说明适用场景
    By.ID 通过元素的 id 属性定位 元素有唯一 id 时(推荐)
    By.NAME 通过元素的 name 属性定位 元素有 name 属性且值唯一时
    By.CLASS_NAME 通过元素的 class 属性定位 元素有 class 属性时(注意:class 可能包含多个值,需完整匹配)
    By.TAG_NAME 通过 HTML 标签名定位 页面中该标签唯一时
    By.LINK_TEXT 通过链接的完整文本定位 定位<a>标签,文本唯一时
    By.PARTIAL_LINK_TEXT 通过链接的部分文本定位 定位<a>标签,只需匹配部分文本
    By.XPATH 通过 XPath 表达式定位 复杂场景,几乎适用于所有情况
    By.CSS_SELECTOR 通过 CSS 选择器定位 复杂场景,语法简洁,性能优于 XPath

    3.2 单元素定位与多元素定位

    Selenium 提供了两类定位方法:

    • 单元素定位:返回第一个匹配的元素,如find_element()
    • 多元素定位:返回所有匹配的元素列表,如find_elements()

    代码示例:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from webdriver_manager.chrome import ChromeDriverManager

    # 初始化浏览器
    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.baidu.com")

    # 1. 通过ID定位(百度搜索框)
    search_box = driver.find_element(By.ID, "kw")
    print("ID定位结果:", search_box.tag_name) # 输出:input

    # 2. 通过NAME定位
    search_box = driver.find_element(By.NAME, "wd")
    print("NAME定位结果:", search_box.get_attribute("id")) # 输出:kw

    # 3. 通过CLASS_NAME定位(百度一下按钮)
    search_button = driver.find_element(By.CLASS_NAME, "s_btn")
    print("CLASS_NAME定位结果:", search_button.get_attribute("value")) # 输出:百度一下

    # 4. 通过TAG_NAME定位(定位所有a标签)
    links = driver.find_elements(By.TAG_NAME, "a")
    print("页面中a标签数量:", len(links)) # 输出:页面中链接的数量

    # 5. 通过LINK_TEXT定位(百度首页的"新闻"链接)
    news_link = driver.find_element(By.LINK_TEXT, "新闻")
    print("LINK_TEXT定位结果:", news_link.get_attribute("href")) # 输出:新闻页面URL

    # 6. 通过PARTIAL_LINK_TEXT定位(包含"地图"的链接)
    map_link = driver.find_element(By.PARTIAL_LINK_TEXT, "地图")
    print("PARTIAL_LINK_TEXT定位结果:", map_link.text) # 输出:地图

    # 7. 通过XPATH定位(搜索框)
    search_box = driver.find_element(By.XPATH, '//*[@id="kw"]')
    print("XPATH定位结果:", search_box.tag_name) # 输出:input

    # 8. 通过CSS_SELECTOR定位(搜索按钮)
    search_button = driver.find_element(By.CSS_SELECTOR, "#su")
    print("CSS_SELECTOR定位结果:", search_button.get_attribute("value")) # 输出:百度一下

    # 关闭浏览器
    driver.quit()

    3.3 XPath 详解

    XPath(XML Path Language)是一种在 XML 文档中定位节点的语言,也适用于 HTML 文档。XPath 功能强大,几乎可以定位到页面上的任何元素。

    3.3.1 绝对路径与相对路径
    • 绝对路径:从根节点/html开始,逐级向下,如/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input

      • 缺点:页面结构稍有变化就会失效,不推荐使用
    • 相对路径:从任意节点开始,以//开头,如//input[@id="kw"]

      • 优点:更灵活,对页面结构变化的容忍度更高,推荐使用
    3.3.2 常用 XPath 表达式
    表达式说明示例
    //标签名 选择所有该标签的元素 //input 选择所有 input 元素
    //@属性名 选择所有具有该属性的元素 //@id 选择所有具有 id 属性的元素
    //标签名[@属性名="值"] 选择属性等于指定值的元素 //input[@name="wd"]
    //标签名[contains(@属性名,"部分值")] 选择属性包含指定部分值的元素 //a[contains(@href,"baidu.com")]
    //标签名[text()="文本"] 选择文本内容等于指定值的元素 //a[text()="新闻"]
    //标签名[contains(text(),"部分文本")] 选择文本包含指定部分的元素 //a[contains(text(),"地图")]
    //标签名[position()=n] 选择第 n 个该标签的元素 //div[position()=1] 选择第一个 div
    //父标签名/子标签名 选择父标签下的子标签 //form/input 选择 form 下的 input

    XPath 代码示例:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from webdriver_manager.chrome import ChromeDriverManager

    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.baidu.com")

    # 1. 定位id为kw的input元素
    element = driver.find_element(By.XPATH, '//input[@id="kw"]')

    # 2. 定位name包含"wd"的元素
    element = driver.find_element(By.XPATH, '//*[contains(@name,"wd")]')

    # 3. 定位文本为"百度一下"的元素
    element = driver.find_element(By.XPATH, '//*[text()="百度一下"]')

    # 4. 定位class包含"bg"的div下的input元素
    element = driver.find_element(By.XPATH, '//div[contains(@class,"bg")]/input')

    # 5. 定位第2个a标签
    element = driver.find_element(By.XPATH, '//a[position()=2]')

    driver.quit()

    3.4 CSS 选择器详解

    CSS 选择器是另一种强大的元素定位方式,语法简洁,性能通常优于 XPath,是很多开发者的首选。

    3.4.1 常用 CSS 选择器语法
    选择器说明示例
    #id 通过 id 定位 #kw 定位 id 为 kw 的元素
    .class 通过 class 定位 .s_btn 定位 class 为 s_btn 的元素
    标签名 通过标签名定位 input 定位所有 input 元素
    标签名#id 标签 + id 定位 input#kw 定位 id 为 kw 的 input 元素
    标签名.class 标签 + class 定位 input.s_ipt 定位 class 为 s_ipt 的 input 元素
    [属性名] 具有指定属性的元素 [name] 定位所有有 name 属性的元素
    [属性名="值"] 属性等于指定值的元素 [name="wd"] 定位 name 为 wd 的元素
    [属性名^="前缀"] 属性以指定前缀开头的元素 [href^="http://"] 定位 href 以 http:// 开头的元素
    [属性名$="后缀"] 属性以指定后缀结尾的元素 [src$=".png"] 定位 src 以.png 结尾的元素
    [属性名*="包含"] 属性包含指定值的元素 [class*="btn"] 定位 class 包含 btn 的元素
    父选择器 子选择器 后代元素 form input 定位 form 下的所有 input 后代
    父选择器>子选择器 直接子元素 div>input 定位 div 的直接子元素 input
    选择器1+选择器2 相邻兄弟元素 input+button 定位 input 后面的第一个 button
    选择器:nth-child(n) 第 n 个子元素 li:nth-child(2) 定位第 2 个 li 元素

    CSS 选择器代码示例:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from webdriver_manager.chrome import ChromeDriverManager

    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.baidu.com")

    # 1. 通过id定位
    element = driver.find_element(By.CSS_SELECTOR, '#kw')

    # 2. 通过class定位
    element = driver.find_element(By.CSS_SELECTOR, '.s_btn')

    # 3. 标签+属性定位
    element = driver.find_element(By.CSS_SELECTOR, 'input[name="wd"]')

    # 4. 属性包含定位
    element = driver.find_element(By.CSS_SELECTOR, '[class*="bg"]')

    # 5. 后代元素定位
    element = driver.find_element(By.CSS_SELECTOR, 'form #kw')

    # 6. 第n个子元素定位
    element = driver.find_element(By.CSS_SELECTOR, 'div:nth-child(1)')

    driver.quit()

    3.5 定位技巧与最佳实践

  • 优先使用 ID:ID 在页面中通常是唯一的,定位速度快且稳定
  • 其次考虑 NAME 或 CLASS:如果没有 ID,可使用这两种方法
  • 复杂场景用 XPath 或 CSS:对于动态生成的元素或复杂结构,使用这两种方法
  • 避免使用绝对路径:维护性差,容易受页面结构变化影响
  • 使用相对定位:提高脚本的稳定性和可维护性
  • 结合多种属性:当单一属性不足以定位时,可组合多个属性
  • 利用开发者工具:浏览器的开发者工具(F12)可以帮助快速定位元素并生成选择器
  • 开发者工具使用技巧:

    • 在页面右键点击元素,选择 "检查" 打开开发者工具
    • 在 Elements 面板中右键点击元素,选择 "Copy" -> "Copy XPath" 或 "Copy selector" 获取定位表达式
    • 注意:自动生成的表达式可能不够简洁,需要手动优化

    四、元素交互:模拟用户操作

    定位到元素后,下一步就是与元素进行交互,模拟用户的各种操作。Selenium 提供了丰富的方法来实现点击、输入、选择等操作。

    4.1 常用元素交互方法

    方法说明
    click() 点击元素(适用于按钮、链接等)
    send_keys(*value) 向输入框发送文本
    clear() 清空输入框内容
    submit() 提交表单(适用于 form 元素)
    get_attribute(name) 获取元素的属性值
    text 获取元素的文本内容
    is_displayed() 判断元素是否可见
    is_enabled() 判断元素是否可用
    is_selected() 判断复选框或单选按钮是否被选中

    代码示例:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from webdriver_manager.chrome import ChromeDriverManager
    import time

    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.baidu.com")

    # 定位搜索框
    search_box = driver.find_element(By.ID, "kw")

    # 1. 输入文本
    search_box.send_keys("Selenium自动化")
    time.sleep(2) # 等待2秒,观察效果

    # 2. 获取属性值
    print("搜索框类型:", search_box.get_attribute("type")) # 输出:text
    print("搜索框名称:", search_box.get_attribute("name")) # 输出:wd

    # 3. 清空内容
    search_box.clear()
    time.sleep(2)

    # 4. 重新输入并提交
    search_box.send_keys("Python")
    search_box.submit() # 提交表单,相当于点击搜索按钮
    time.sleep(3)

    # 5. 定位搜索结果标题并获取文本
    result_title = driver.find_element(By.XPATH, '//*[@id="1"]/h3/a')
    print("第一个搜索结果标题:", result_title.text)

    # 6. 判断元素状态
    print("结果标题是否可见:", result_title.is_displayed()) # 输出:True

    # 7. 点击搜索结果
    result_title.click()
    time.sleep(5)

    # 关闭浏览器
    driver.quit()

    4.2 处理表单元素

    表单是 Web 应用中最常见的交互元素,包括文本框、密码框、复选框、单选按钮、下拉菜单等。

    4.2.1 处理复选框和单选按钮

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from webdriver_manager.chrome import ChromeDriverManager
    import time

    # 访问一个包含表单的测试页面
    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.w3schools.com/html/html_forms.asp")

    # 切换到包含表单的iframe(示例页面的表单在iframe中)
    driver.switch_to.frame("iframeResult")

    # 1. 处理复选框
    checkbox1 = driver.find_element(By.XPATH, '//input[@value="vehicle1"]')
    checkbox2 = driver.find_element(By.XPATH, '//input[@value="vehicle2"]')

    # 勾选复选框(如果未勾选)
    if not checkbox1.is_selected():
    checkbox1.click()
    time.sleep(2)

    if not checkbox2.is_selected():
    checkbox2.click()
    time.sleep(2)

    # 取消勾选第一个复选框
    if checkbox1.is_selected():
    checkbox1.click()
    time.sleep(2)

    # 2. 处理单选按钮
    radio1 = driver.find_element(By.XPATH, '//input[@value="male"]')
    radio2 = driver.find_element(By.XPATH, '//input[@value="female"]')

    # 选择第一个单选按钮
    if not radio1.is_selected():
    radio1.click()
    time.sleep(2)

    # 选择第二个单选按钮
    if not radio2.is_selected():
    radio2.click()
    time.sleep(2)

    # 退出iframe
    driver.switch_to.default_content()

    driver.quit()

    4.2.2 处理下拉菜单

    下拉菜单(<select>元素)是表单中的特殊元素,Selenium 提供了Select类专门处理:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import Select
    from webdriver_manager.chrome import ChromeDriverManager
    import time

    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select")

    # 切换到iframe
    driver.switch_to.frame("iframeResult")

    # 定位select元素并创建Select对象
    select_element = driver.find_element(By.TAG_NAME, "select")
    select = Select(select_element)

    # 1. 通过索引选择(索引从0开始)
    select.select_by_index(1) # 选择第二个选项
    time.sleep(2)

    # 2. 通过可见文本选择
    select.select_by_visible_text("Saab")
    time.sleep(2)

    # 3. 通过value属性选择
    select.select_by_value("opel")
    time.sleep(2)

    # 获取所有选项
    options = select.options
    print("所有选项:")
    for option in options:
    print(option.text)

    # 获取当前选中的选项
    selected_option = select.first_selected_option
    print("当前选中的选项:", selected_option.text)

    # 退出iframe
    driver.switch_to.default_content()

    driver.quit()

    4.3 处理文件上传和下载

    文件上传和下载是 Web 应用中常见的功能,Selenium 提供了相应的处理方法。

    4.3.1 文件上传

    文件上传通常通过<input type="file">元素实现,Selenium 可以直接向该元素发送文件路径:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from webdriver_manager.chrome import ChromeDriverManager
    import time
    import os

    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_input_type_file")

    # 切换到iframe
    driver.switch_to.frame("iframeResult")

    # 定位文件上传元素
    file_input = driver.find_element(By.ID, "myFile")

    # 获取当前脚本所在目录
    current_dir = os.path.dirname(os.path.abspath(__file__))
    # 要上传的文件路径(替换为实际文件路径)
    file_path = os.path.join(current_dir, "test.txt")

    # 发送文件路径到文件上传元素
    file_input.send_keys(file_path)
    time.sleep(3)

    # 退出iframe
    driver.switch_to.default_content()

    driver.quit()

    注意:确保test.txt文件存在于脚本所在目录,或使用绝对路径。

    4.3.2 文件下载

    文件下载需要配置浏览器的下载路径,不同浏览器的配置方式略有不同:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.chrome.options import Options
    from webdriver_manager.chrome import ChromeDriverManager
    import time
    import os

    # 配置Chrome浏览器的下载设置
    chrome_options = Options()
    # 设置下载路径(替换为实际路径)
    download_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "downloads")
    # 创建下载目录(如果不存在)
    os.makedirs(download_dir, exist_ok=True)

    # 配置下载选项
    prefs = {
    "download.default_directory": download_dir, # 下载路径
    "download.prompt_for_download": False, # 不提示下载
    "download.directory_upgrade": True,
    "safebrowsing.enabled": True # 启用安全浏览
    }
    chrome_options.add_experimental_option("prefs", prefs)

    # 初始化浏览器
    driver = webdriver.Chrome(
    ChromeDriverManager().install(),
    options=chrome_options
    )

    # 访问一个提供下载的页面(示例)
    driver.get("https://www.w3schools.com/python/python_intro.asp")

    # 定位并点击下载链接(示例)
    # 注意:实际页面的下载链接可能不同,需要根据实际情况修改
    try:
    download_link = driver.find_element(By.LINK_TEXT, "Download Python")
    download_link.click()
    print("开始下载…")
    time.sleep(10) # 等待下载完成(根据文件大小调整)
    print(f"文件已下载到:{download_dir}")
    except Exception as e:
    print("未找到下载链接:", e)

    driver.quit()

    五、浏览器控制与导航

    除了元素交互,Selenium 还可以控制浏览器本身,如调整窗口大小、前进后退、刷新页面等。

    5.1 浏览器窗口控制

    python

    运行

    from selenium import webdriver
    from webdriver_manager.chrome import ChromeDriverManager
    import time

    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.baidu.com")
    time.sleep(2)

    # 1. 设置窗口大小
    driver.set_window_size(1024, 768) # 宽1024,高768
    time.sleep(2)

    # 2. 最大化窗口
    driver.maximize_window()
    time.sleep(2)

    # 3. 最小化窗口
    driver.minimize_window()
    time.sleep(2)

    # 4. 全屏显示
    driver.fullscreen_window()
    time.sleep(2)

    # 5. 获取窗口大小
    window_size = driver.get_window_size()
    print(f"窗口大小:宽{window_size['width']},高{window_size['height']}")

    # 6. 设置窗口位置(左上角坐标)
    driver.set_window_position(100, 100)
    time.sleep(2)

    # 7. 获取窗口位置
    window_position = driver.get_window_position()
    print(f"窗口位置:x={window_position['x']},y={window_position['y']}")

    driver.quit()

    5.2 页面导航

    python

    运行

    from selenium import webdriver
    from webdriver_manager.chrome import ChromeDriverManager
    import time

    driver = webdriver.Chrome(ChromeDriverManager().install())

    # 1. 打开网页
    driver.get("https://www.baidu.com")
    print("当前URL:", driver.current_url)
    print("页面标题:", driver.title)
    time.sleep(2)

    # 2. 打开另一个网页
    driver.get("https://www.bing.com")
    print("当前URL:", driver.current_url)
    print("页面标题:", driver.title)
    time.sleep(2)

    # 3. 后退
    driver.back()
    print("后退后URL:", driver.current_url)
    time.sleep(2)

    # 4. 前进
    driver.forward()
    print("前进后URL:", driver.current_url)
    time.sleep(2)

    # 5. 刷新页面
    driver.refresh()
    time.sleep(2)

    # 6. 获取页面源码
    page_source = driver.page_source
    print("页面源码长度:", len(page_source))

    driver.quit()

    5.3 多窗口与 iframe 切换

    现代 Web 应用经常使用多窗口或 iframe(内嵌框架),Selenium 需要切换到相应的上下文才能操作其中的元素。

    5.3.1 多窗口切换

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from webdriver_manager.chrome import ChromeDriverManager
    import time

    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.baidu.com")
    time.sleep(2)

    # 获取当前窗口句柄(唯一标识)
    original_window = driver.current_window_handle
    print("原始窗口句柄:", original_window)

    # 打开新窗口(通过JavaScript)
    driver.execute_script("window.open('https://www.bing.com');")
    time.sleep(2)

    # 获取所有窗口句柄
    all_windows = driver.window_handles
    print("所有窗口句柄:", all_windows)

    # 切换到新窗口
    for window in all_windows:
    if window != original_window:
    driver.switch_to.window(window)
    break

    print("切换后窗口URL:", driver.current_url)
    time.sleep(2)

    # 在新窗口中执行操作
    search_box = driver.find_element(By.NAME, "q")
    search_box.send_keys("Selenium")
    search_box.submit()
    time.sleep(3)

    # 切换回原始窗口
    driver.switch_to.window(original_window)
    print("切换回原始窗口URL:", driver.current_url)
    time.sleep(2)

    # 关闭当前窗口(新窗口)
    driver.switch_to.window(all_windows[1])
    driver.close()
    time.sleep(2)

    # 切换回原始窗口并继续操作
    driver.switch_to.window(original_window)
    print("最终窗口URL:", driver.current_url)

    driver.quit()

    5.3.2 iframe 切换

    iframe 是内嵌在页面中的另一个 HTML 文档,需要先切换到 iframe 才能操作其中的元素:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from webdriver_manager.chrome import ChromeDriverManager
    import time

    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.w3schools.com/html/tryit.asp?filename=tryhtml_iframe")
    time.sleep(2)

    # 1. 通过id或name切换iframe
    driver.switch_to.frame("iframeResult")
    time.sleep(2)

    # 在iframe中操作元素
    heading = driver.find_element(By.TAG_NAME, "h1")
    print("iframe中的标题:", heading.text)
    time.sleep(2)

    # 2. 切换到嵌套的iframe(iframe中的iframe)
    nested_iframe = driver.find_element(By.TAG_NAME, "iframe")
    driver.switch_to.frame(nested_iframe)
    time.sleep(2)

    # 在嵌套iframe中操作
    nested_heading = driver.find_element(By.TAG_NAME, "h1")
    print("嵌套iframe中的标题:", nested_heading.text)
    time.sleep(2)

    # 3. 切换回父级iframe
    driver.switch_to.parent_frame()
    time.sleep(2)

    # 4. 切换回主文档
    driver.switch_to.default_content()
    time.sleep(2)

    # 在主文档中操作
    menu_item = driver.find_element(By.LINK_TEXT, "HTML Tutorial")
    print("主文档中的菜单:", menu_item.text)

    driver.quit()

    5.4 处理 JavaScript 弹窗

    Web 页面中常见的弹窗有三种:alert(警告框)、confirm(确认框)、prompt(提示框),Selenium 提供了相应的处理方法:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from webdriver_manager.chrome import ChromeDriverManager
    import time

    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get("https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert")
    time.sleep(2)

    # 切换到iframe
    driver.switch_to.frame("iframeResult")

    # 1. 处理alert弹窗
    alert_button = driver.find_element(By.XPATH, '//button[text()="Try it"]')
    alert_button.click()
    time.sleep(2)

    # 切换到alert
    alert = driver.switch_to.alert
    print("Alert文本:", alert.text)

    # 接受alert(点击确定)
    alert.accept()
    time.sleep(2)

    # 2. 处理confirm弹窗
    driver.get("https://www.w3schools.com/js/tryit.asp?filename=tryjs_confirm")
    driver.switch_to.frame("iframeResult")
    confirm_button = driver.find_element(By.XPATH, '//button[text()="Try it"]')
    confirm_button.click()
    time.sleep(2)

    confirm = driver.switch_to.alert
    print("Confirm文本:", confirm.text)

    # 取消confirm(点击取消)
    confirm.dismiss()
    time.sleep(2)

    # 3. 处理prompt弹窗
    driver.get("https://www.w3schools.com/js/tryit.asp?filename=tryjs_prompt")
    driver.switch_to.frame("iframeResult")
    prompt_button = driver.find_element(By.XPATH, '//button[text()="Try it"]')
    prompt_button.click()
    time.sleep(2)

    prompt = driver.switch_to.alert
    print("Prompt文本:", prompt.text)

    # 向prompt输入文本并确认
    prompt.send_keys("Selenium")
    prompt.accept()
    time.sleep(2)

    # 退出iframe
    driver.switch_to.default_content()

    driver.quit()

    六、等待机制:处理页面加载与动态内容

    在 Web 自动化中,页面元素的加载往往不是瞬间完成的,特别是使用 AJAX 或 JavaScript 动态生成的内容。如果脚本执行速度快于元素加载速度,就会导致 "元素未找到" 的错误。Selenium 提供了三种等待机制来解决这个问题。

    6.1 强制等待(sleep)

    强制等待是最简单的等待方式,使用time.sleep(seconds)让脚本暂停指定的秒数:

    python

    运行

    import time
    from selenium import webdriver
    from selenium.webdriver.common.by import By

    driver = webdriver.Chrome()
    driver.get("https://www.baidu.com")

    # 强制等待2秒
    time.sleep(2)

    search_box = driver.find_element(By.ID, "kw")
    search_box.send_keys("Selenium")
    search_box.submit()

    # 强制等待3秒,等待搜索结果加载
    time.sleep(3)

    result = driver.find_element(By.XPATH, '//*[@id="1"]/h3/a')
    print(result.text)

    driver.quit()

    缺点:

    • 无论元素是否已经加载,都会等待固定时间,降低脚本执行效率
    • 难以确定合适的等待时间(设置太短可能仍会出错,设置太长则浪费时间)

    6.2 隐性等待(Implicit Wait)

    隐性等待设置一个全局的等待时间,在这个时间内 Selenium 会不断尝试查找元素,直到元素被找到或超时:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By

    driver = webdriver.Chrome()
    # 设置隐性等待时间为10秒
    driver.implicitly_wait(10)

    driver.get("https://www.baidu.com")

    search_box = driver.find_element(By.ID, "kw")
    search_box.send_keys("Selenium")
    search_box.submit()

    # 最多等待10秒,直到元素出现
    result = driver.find_element(By.XPATH, '//*[@id="1"]/h3/a')
    print(result.text)

    driver.quit()

    特点:

    • 只需设置一次,对整个 driver 生命周期有效
    • 等待元素被找到,但不等待元素可交互
    • 超时后会抛出NoSuchElementException

    6.3 显性等待(Explicit Wait)

    显性等待是最灵活、最推荐的等待方式,它允许我们等待某个条件满足(如元素可见、可点击等),并可以设置超时时间和轮询间隔:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC

    driver = webdriver.Chrome()
    driver.get("https://www.baidu.com")

    search_box = driver.find_element(By.ID, "kw")
    search_box.send_keys("Selenium")
    search_box.submit()

    # 创建WebDriverWait对象,设置超时时间为10秒
    wait = WebDriverWait(driver, 10)

    # 等待元素可见(最多10秒)
    result = wait.until(
    EC.visibility_of_element_located((By.XPATH, '//*[@id="1"]/h3/a'))
    )
    print(result.text)

    # 其他常用条件
    # 等待元素可点击
    # button = wait.until(EC.element_to_be_clickable((By.ID, "button_id")))

    # 等待元素存在于DOM中
    # element = wait.until(EC.presence_of_element_located((By.ID, "element_id")))

    # 等待标题包含指定文本
    # wait.until(EC.title_contains("Selenium"))

    driver.quit()

    6.3.1 常用的 Expected Conditions

    expected_conditions模块提供了多种预定义的条件,常用的有:

    条件说明
    title_is(title) 页面标题等于指定标题
    title_contains(substring) 页面标题包含指定子串
    presence_of_element_located(locator) 元素存在于 DOM 中
    visibility_of_element_located(locator) 元素可见(存在且可见)
    visibility_of(element) 已知元素可见
    element_to_be_clickable(locator) 元素可点击
    element_located_to_be_selected(locator) 元素被选中
    text_to_be_present_in_element(locator, text) 元素包含指定文本
    text_to_be_present_in_element_value(locator, text) 元素的 value 属性包含指定文本
    frame_to_be_available_and_switch_to_it(locator) iframe 可用并切换到该 iframe
    invisibility_of_element_located(locator) 元素不可见
    alert_is_present() 存在 alert 弹窗
    6.3.2 自定义等待条件

    如果预定义的条件不能满足需求,我们可以定义自己的等待条件:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait

    driver = webdriver.Chrome()
    driver.get("https://www.baidu.com")

    search_box = driver.find_element(By.ID, "kw")
    search_box.send_keys("Selenium")
    search_box.submit()

    # 自定义条件:等待元素文本长度大于10
    def text_length_greater_than_10(driver):
    element = driver.find_element(By.XPATH, '//*[@id="1"]/h3/a')
    return len(element.text) > 10

    # 应用自定义条件
    wait = WebDriverWait(driver, 10)
    result = wait.until(text_length_greater_than_10)
    print(f"满足条件的元素文本:{result.text},长度:{len(result.text)}")

    driver.quit()

    6.4 等待机制最佳实践

  • 优先使用显性等待:灵活性高,只在需要等待的地方应用,不影响其他操作
  • 合理设置超时时间:根据页面加载速度设置,一般 3-10 秒
  • 避免混合使用隐性等待和显性等待:可能导致不可预测的等待时间
  • 针对不同操作选择合适的条件:
    • 读取文本:使用visibility_of_element_located(确保元素可见)
    • 点击按钮:使用element_to_be_clickable(确保元素可点击)
    • 判断元素存在:使用presence_of_element_located(只需存在于 DOM 中)
  • 结合使用强制等待:在极少数情况下,如页面跳转、文件下载等,可配合使用
  • 七、Selenium 自动化测试框架集成

    Selenium 不仅可以用于网页爬取,更是自动化测试的利器。将 Selenium 与 Python 的单元测试框架(如 unittest 或 pytest)结合,可以构建强大的自动化测试套件。

    7.1 与 unittest 集成

    unittest 是 Python 内置的单元测试框架,提供了测试用例、测试套件、断言等功能:

    python

    运行

    import unittest
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from webdriver_manager.chrome import ChromeDriverManager

    class TestBaiduSearch(unittest.TestCase):
    # 在所有测试方法执行前运行
    def setUp(self):
    self.driver = webdriver.Chrome(ChromeDriverManager().install())
    self.driver.maximize_window()
    self.driver.get("https://www.baidu.com")
    self.wait = WebDriverWait(self.driver, 10)

    # 在所有测试方法执行后运行
    def tearDown(self):
    self.driver.quit()

    # 测试方法必须以test开头
    def test_search_selenium(self):
    # 定位搜索框并输入内容
    search_box = self.wait.until(
    EC.element_to_be_clickable((By.ID, "kw"))
    )
    search_box.clear()
    search_box.send_keys("Selenium")

    # 点击搜索按钮
    search_button = self.driver.find_element(By.ID, "su")
    search_button.click()

    # 验证搜索结果
    result = self.wait.until(
    EC.visibility_of_element_located((By.XPATH, '//*[@id="1"]/h3/a'))
    )
    self.assertIn("Selenium", result.text, "搜索结果不包含预期文本")

    def test_search_python(self):
    # 定位搜索框并输入内容
    search_box = self.wait.until(
    EC.element_to_be_clickable((By.ID, "kw"))
    )
    search_box.clear()
    search_box.send_keys("Python")

    # 点击搜索按钮
    search_button = self.driver.find_element(By.ID, "su")
    search_button.click()

    # 验证搜索结果
    result = self.wait.until(
    EC.visibility_of_element_located((By.XPATH, '//*[@id="1"]/h3/a'))
    )
    self.assertIn("Python", result.text, "搜索结果不包含预期文本")

    if __name__ == "__main__":
    # 运行所有测试
    unittest.main()

    7.2 与 pytest 集成

    pytest 是比 unittest 更灵活的测试框架,支持更简洁的语法和丰富的插件:

    首先安装 pytest:

    bash

    pip install pytest

    测试代码:

    python

    运行

    import pytest
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from webdriver_manager.chrome import ChromeDriverManager

    # 测试前的准备工作
    @pytest.fixture(scope="module")
    def driver():
    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.maximize_window()
    driver.get("https://www.baidu.com")
    yield driver # 测试完成后执行后续代码
    driver.quit()

    # 测试搜索功能
    def test_search_selenium(driver):
    wait = WebDriverWait(driver, 10)

    # 输入搜索内容
    search_box = wait.until(
    EC.element_to_be_clickable((By.ID, "kw"))
    )
    search_box.clear()
    search_box.send_keys("Selenium")

    # 点击搜索
    driver.find_element(By.ID, "su").click()

    # 验证结果
    result = wait.until(
    EC.visibility_of_element_located((By.XPATH, '//*[@id="1"]/h3/a'))
    )
    assert "Selenium" in result.text, "搜索结果不包含预期文本"

    # 参数化测试:测试多个搜索关键词
    @pytest.mark.parametrize("keyword", ["Python", "Java", "JavaScript"])
    def test_search_parametrized(driver, keyword):
    wait = WebDriverWait(driver, 10)

    # 输入搜索内容
    search_box = wait.until(
    EC.element_to_be_clickable((By.ID, "kw"))
    )
    search_box.clear()
    search_box.send_keys(keyword)

    # 点击搜索
    driver.find_element(By.ID, "su").click()

    # 验证结果
    result = wait.until(
    EC.visibility_of_element_located((By.XPATH, '//*[@id="1"]/h3/a'))
    )
    assert keyword in result.text, f"搜索{keyword}的结果不包含预期文本"

    运行测试:

    bash

    pytest test_baidu.py -v # -v 显示详细信息

    7.3 生成测试报告

    使用 pytest-html 插件可以生成美观的 HTML 测试报告:

    安装插件:

    bash

    pip install pytest-html

    运行测试并生成报告:

    bash

    pytest test_baidu.py -v –html=report.html

    运行完成后,会生成 report.html 文件,包含测试结果、执行时间、错误信息等详细内容。

    八、网页数据爬取实战

    Selenium 不仅用于自动化测试,也是网页爬取的重要工具,特别适合处理 JavaScript 动态渲染的页面。下面通过几个实战案例展示 Selenium 在数据爬取中的应用。

    8.1 爬取静态网页数据

    以爬取豆瓣电影 Top250 为例:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from webdriver_manager.chrome import ChromeDriverManager
    import time
    import csv

    def crawl_douban_top250():
    # 初始化浏览器
    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.maximize_window()
    wait = WebDriverWait(driver, 10)

    # 存储结果
    movies = []

    try:
    # 爬取10页数据
    for page in range(10):
    url = f"https://movie.douban.com/top250?start={page*25}&filter="
    driver.get(url)
    print(f"正在爬取第{page+1}页:{url}")

    # 等待页面加载完成
    wait.until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, ".grid_view li"))
    )

    # 获取当前页的电影列表
    movie_list = driver.find_elements(By.CSS_SELECTOR, ".grid_view li")

    for movie in movie_list:
    # 提取电影信息
    title = movie.find_element(By.CSS_SELECTOR, ".title").text
    rating = movie.find_element(By.CSS_SELECTOR, ".rating_num").text
    info = movie.find_element(By.CSS_SELECTOR, ".bd p:first-child").text
    quote = movie.find_element(By.CSS_SELECTOR, ".inq").text if movie.find_elements(By.CSS_SELECTOR, ".inq") else ""

    movies.append({
    "排名": len(movies) + 1,
    "标题": title,
    "评分": rating,
    "信息": info,
    "引言": quote
    })

    time.sleep(2) # 避免爬取过快被反爬

    # 保存数据到CSV文件
    with open("douban_top250.csv", "w", encoding="utf-8-sig", newline="") as f:
    fieldnames = ["排名", "标题", "评分", "信息", "引言"]
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(movies)

    print(f"爬取完成,共{len(movies)}部电影,已保存到douban_top250.csv")

    except Exception as e:
    print(f"爬取过程中出错:{e}")

    finally:
    driver.quit()

    if __name__ == "__main__":
    crawl_douban_top250()

    8.2 爬取动态加载数据

    很多网站采用滚动加载或点击加载更多的方式加载数据,如 Twitter、知乎等。下面以爬取滚动加载的页面为例:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from webdriver_manager.chrome import ChromeDriverManager
    import time
    import csv
    import random

    def crawl_scroll_page():
    # 初始化浏览器
    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.maximize_window()
    wait = WebDriverWait(driver, 10)

    # 访问目标页面(示例:知乎话题下的回答)
    url = "https://www.zhihu.com/topic/19552832/top-answers"
    driver.get(url)
    print(f"访问页面:{url}")

    # 存储结果
    answers = []

    try:
    # 等待页面加载
    wait.until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, ".List-item"))
    )

    # 滚动次数(根据需要调整)
    scroll_count = 10
    last_height = driver.execute_script("return document.body.scrollHeight")

    for i in range(scroll_count):
    print(f"第{i+1}次滚动")

    # 滚动到页面底部
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # 随机等待2-5秒,模拟人类行为
    sleep_time = random.uniform(2, 5)
    print(f"等待{sleep_time:.2f}秒")
    time.sleep(sleep_time)

    # 计算新的页面高度并与上一次比较
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
    print("页面已滚动到底部,没有更多内容")
    break
    last_height = new_height

    # 提取所有回答
    answer_elements = driver.find_elements(By.CSS_SELECTOR, ".List-item")
    print(f"共找到{len(answer_elements)}个回答")

    for idx, element in enumerate(answer_elements):
    try:
    # 提取回答者
    author = element.find_element(By.CSS_SELECTOR, ".UserLink-link").text

    # 提取回答内容(简化版)
    content = element.find_element(By.CSS_SELECTOR, ".RichText").text[:200] # 只取前200字

    # 提取点赞数
    vote = element.find_element(By.CSS_SELECTOR, ".VoteButton-count").text

    answers.append({
    "序号": idx + 1,
    "作者": author,
    "点赞数": vote,
    "内容": content
    })
    except Exception as e:
    print(f"提取第{idx+1}个回答时出错:{e}")
    continue

    # 保存数据
    with open("zhihu_answers.csv", "w", encoding="utf-8-sig", newline="") as f:
    fieldnames = ["序号", "作者", "点赞数", "内容"]
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(answers)

    print(f"爬取完成,共{len(answers)}个回答,已保存到zhihu_answers.csv")

    except Exception as e:
    print(f"爬取过程中出错:{e}")

    finally:
    driver.quit()

    if __name__ == "__main__":
    crawl_scroll_page()

    8.3 处理登录验证

    很多网站需要登录才能访问完整内容,Selenium 可以模拟登录过程:

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from webdriver_manager.chrome import ChromeDriverManager
    import time
    import getpass # 用于安全输入密码

    def simulate_login():
    # 初始化浏览器
    driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.maximize_window()
    wait = WebDriverWait(driver, 10)

    try:
    # 访问登录页面(示例:GitHub登录)
    driver.get("https://github.com/login")
    print("已打开GitHub登录页面")

    # 输入用户名
    username_input = wait.until(
    EC.element_to_be_clickable((By.ID, "login_field"))
    )
    username = input("请输入GitHub用户名:")
    username_input.send_keys(username)

    # 输入密码
    password_input = driver.find_element(By.ID, "password")
    password = getpass.getpass("请输入GitHub密码:") # 密码不显示在终端
    password_input.send_keys(password)

    # 点击登录按钮
    login_button = driver.find_element(By.NAME, "commit")
    login_button.click()
    time.sleep(3)

    # 验证登录是否成功(检查是否跳转到首页)
    try:
    wait.until(EC.url_contains("github.com"))
    print("登录成功!")

    # 登录后的操作(例如访问个人主页)
    driver.get(f"https://github.com/{username}")
    wait.until(EC.title_contains(username))
    print(f"已进入{username}的个人主页")
    time.sleep(5)

    except Exception as e:
    print("登录失败:", e)

    except Exception as e:
    print(f"登录过程中出错:{e}")

    finally:
    driver.quit()

    if __name__ == "__main__":
    simulate_login()

    注意:自动化登录可能违反某些网站的用户协议,且可能触发验证码等反爬机制。在实际应用中,请遵守网站的 robots 协议和使用条款。

    九、Selenium 性能优化与最佳实践

    9.1 性能优化技巧

  • 使用无头浏览器:在不需要可视化界面的场景(如服务器环境),使用无头模式可以显著提高性能

    python

    运行

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options

    chrome_options = Options()
    chrome_options.add_argument("–headless=new") # 无头模式
    chrome_options.add_argument("–disable-gpu") # 禁用GPU加速
    driver = webdriver.Chrome(options=chrome_options)

  • 禁用不必要的功能:关闭图片加载、JavaScript 等非必要功能(根据需求)

    python

    运行

    chrome_options = Options()
    # 禁用图片加载
    prefs = {"profile.managed_default_content_settings.images": 2}
    chrome_options.add_experimental_option("prefs", prefs)
    # 禁用JavaScript
    chrome_options.add_argument("–disable-javascript")

  • 减少等待时间:合理设置等待时间,避免不必要的等待

  • 复用浏览器实例:在多个测试用例或爬取任务中复用同一个浏览器实例,减少启动开销

  • 使用更快的选择器:优先使用 ID、NAME 等快速定位方式,CSS 选择器性能通常优于 XPath

  • 批量操作:使用 JavaScript 执行批量操作,减少与浏览器的交互次数

    python

    运行

    # 批量设置多个元素的文本
    js_code = """
    var elements = document.getElementsByClassName('item');
    for(var i=0; i<elements.length; i++){
    elements[i].textContent = 'new text';
    }
    """
    driver.execute_script(js_code)

  • 9.2 最佳实践

  • 元素定位策略:

    • 优先使用 ID,其次是 NAME、CLASS
    • 复杂场景使用相对 XPath 或 CSS 选择器
    • 避免使用绝对路径和动态生成的属性
    • 为测试环境的元素添加稳定的测试 ID
  • 代码组织:

    • 使用 Page Object 模式封装页面操作,提高代码复用性和可维护性
    • 将配置信息(如 URL、等待时间)与业务逻辑分离
    • 异常处理:捕获并处理可能的异常(如元素未找到、超时等)
  • 反爬与合规:

    • 遵守网站的 robots 协议和使用条款
    • 模拟人类行为(合理的等待时间、随机操作间隔)
    • 避免频繁请求,设置请求间隔
    • 必要时使用代理 IP 和 User-Agent 池
  • 测试实践:

    • 保持测试用例的独立性,每个用例应能单独运行
    • 测试数据与测试代码分离
    • 定期维护测试用例,适应页面变化
    • 结合 CI/CD 工具(如 Jenkins)实现持续测试
  • 调试技巧:

    • 使用driver.save_screenshot()在关键步骤截图,便于调试
    • 利用print()或日志输出关键信息
    • 使用浏览器开发者工具分析页面结构和网络请求
  • 十、总结与展望

    Selenium 作为一款成熟的 Web 自动化工具,已经成为测试工程师和数据爬取爱好者的必备技能。它强大的浏览器控制能力、跨平台跨浏览器的特性以及丰富的 API,使其能够应对各种复杂的 Web 自动化场景。

    本文从 Selenium 的基本概念出发,详细介绍了环境搭建、元素定位、交互操作、浏览器控制、等待机制等核心内容,并通过大量代码示例展示了 Selenium 在自动化测试和网页爬取中的应用。同时,我们也探讨了性能优化和最佳实践,帮助读者编写更高效、更稳定的自动化脚本。

    随着 Web 技术的不断发展,Selenium 也在持续进化。未来,Selenium 将更好地支持现代 Web 框架(如 React、Vue)和新兴浏览器特性,同时在性能和易用性上不断提升。掌握 Selenium 不仅能够提高工作效率,更能为从事测试开发、数据采集等领域的工作打下坚实基础。

    无论是自动化测试工程师、数据分析师还是开发人员,都可以通过 Selenium 打开 Web 自动化的大门,探索更多可能性。希望本文能够帮助你快速入门并精通 Selenium,让自动化技术为你的工作带来更多价值。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 全面了解selenium
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!