杰瑞科技汇

Python WebDriver实战如何快速上手?

目录

  1. 什么是 WebDriver?为什么选择它?
  2. 环境准备
    • 安装 Python
    • 安装 Selenium 库
    • 安装浏览器驱动
  3. 第一个 WebDriver 脚本:打开网页
  4. 核心实战:元素定位
    • 什么是元素?
    • 8 种定位方式详解(附实战案例)
    • 定不到元素怎么办?(常见问题与解决方案)
  5. 实战:元素交互
    • 点击、输入、清空、获取文本/属性
    • 处下拉框
    • 处弹窗
  6. 实战:等待策略
    • 强制等待
    • 隐式等待
    • 显式等待(重点)
  7. 实战:多窗口/多标签页处理
  8. 实战:实战案例:自动化登录与信息抓取
    • 目标网站分析
    • 编写完整代码
    • 代码讲解
  9. 高级技巧与最佳实践
    • 无头模式
    • 使用 Options 配置浏览器
    • 页面截图与源码保存
    • 使用 try...except 处理异常
    • 使用 with 语句管理浏览器
  10. 总结与展望

什么是 WebDriver?为什么选择它?

  • WebDriver 是一个用于 Web 应用程序自动化测试的工具,它允许你的 Python 脚本像真实用户一样在浏览器中操作,比如点击按钮、输入文本、导航链接等。
  • 核心原理:WebDriver 启动一个真实的浏览器(如 Chrome、Firefox),并通过一个协议(如 W3C WebDriver Protocol)向浏览器发送指令,浏览器执行这些指令并将结果返回给脚本。
  • 为什么选择它?
    • 真实环境:在真实的浏览器中运行,可以模拟真实用户的操作,处理复杂的 JavaScript 渲染页面。
    • 跨平台:支持 Windows, macOS, Linux。
    • 多语言支持:除了 Python,还支持 Java, C#, Ruby, JavaScript 等。
    • 强大的社区:Selenium 拥有庞大的用户社区和丰富的文档,遇到问题很容易找到解决方案。

环境准备

安装 Python

确保你已经安装了 Python 3.6+,在终端/命令行中输入:

Python WebDriver实战如何快速上手?-图1
(图片来源网络,侵删)
python --version

如果没有安装,请从 Python 官网 下载并安装。

安装 Selenium 库

打开终端/命令行,使用 pip 安装:

pip install selenium

安装浏览器驱动

WebDriver 需要一个“翻译官”来告诉浏览器该做什么,这个“翻译官”浏览器驱动,你需要为你的浏览器下载对应的驱动。

以 Chrome 为例(最常用):

Python WebDriver实战如何快速上手?-图2
(图片来源网络,侵删)
  1. 确认 Chrome 版本:打开 Chrome 浏览器 -> 设置 -> Chrome,记下你的 Chrome 版本号(0.6312.86)。
  2. 下载驱动
    • 访问 Chrome for Testing availability (Google 提供的官方镜像)。
    • 找到与你 Chrome 版本号最接近的 chromedriver
    • 根据你的操作系统下载对应的文件(chromedriver-win64.zip)。
  3. 配置驱动路径
    • 方法一(推荐,最简单):将下载的 chromedriver.exe (Windows) 或 chromedriver (Mac/Linux) 文件,直接放到你的 Python 脚本所在的同一目录下,这样 WebDriver 会自动找到它。
    • 方法二:将驱动文件所在目录添加到系统的 PATH 环境变量中。

第一个 WebDriver 脚本:打开网页

创建一个名为 first_script.py 的文件,输入以下代码:

# 1. 导入 WebDriver
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
# 2. 指定 chromedriver 的路径
# chromedriver 和脚本在同一目录,可以省略此步
# service = Service(executable_path='chromedriver.exe') 
# driver = webdriver.Chrome(service=service)
# chromedriver 在 PATH 中,可以直接这样写
driver = webdriver.Chrome()
# 3. 打开一个网页
driver.get("https://www.baidu.com")
# 4. 打印页面标题
print("页面标题是:", driver.title)
# 5. 关闭浏览器
# driver.quit() # 退出并关闭所有窗口
driver.close() # 关闭当前窗口

运行这个脚本 (python first_script.py),你会看到一个 Chrome 浏览器自动打开,导航到百度首页,然后自动关闭,恭喜,你已经成功迈出了第一步!


核心实战:元素定位

自动化测试的核心就是找到页面上的元素,然后对它进行操作,Selenium 提供了 8 种强大的定位方式。

定位方式总结:

Python WebDriver实战如何快速上手?-图3
(图片来源网络,侵删)
定位方式 Python 语法 描述 优先级
ID driver.find_element(By.ID, "value") 通过元素的 id 属性定位 最高
Name driver.find_element(By.NAME, "value") 通过元素的 name 属性定位
Class Name driver.find_element(By.CLASS_NAME, "value") 通过元素的 class 属性定位
Tag Name driver.find_element(By.TAG_NAME, "value") 通过元素的标签名定位
Link Text driver.find_element(By.LINK_TEXT, "value") 通过超链接的完整文本定位
Partial Link Text driver.find_element(By.PARTIAL_LINK_TEXT, "value") 通过超链接的部分文本定位
CSS Selector driver.find_element(By.CSS_SELECTOR, "value") 通过 CSS 选择器定位
XPath driver.find_element(By.XPATH, "value") 通过 XPath 路径定位

实战案例:在百度搜索框输入文字

打开百度首页,右键点击搜索框 -> “检查”,你会看到类似这样的 HTML 代码:

<input id="kw" class="s_ipt" type="text" maxlength="255" autocomplete="off" maxlength="255">

我们可以用多种方式定位它:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.implicitly_wait(10) # 隐式等待,后面会讲到
try:
    # 1. 通过 ID 定位 (最推荐)
    search_box_by_id = driver.find_element(By.ID, "kw")
    print("通过 ID 定位成功!")
    # 2. 通过 Name 定位
    search_box_by_name = driver.find_element(By.NAME, "wd")
    print("通过 Name 定位成功!")
    # 3. 通过 Class Name 定位
    # 注意:class 可能有多个空格隔开的值,通常取第一个
    search_box_by_class = driver.find_element(By.CLASS_NAME, "s_ipt")
    print("通过 Class Name 定位成功!")
    # 4. 通过 CSS Selector 定位 (非常强大和灵活)
    # 通过 ID
    search_box_css_id = driver.find_element(By.CSS_SELECTOR, "#kw")
    # 通过 class
    search_box_css_class = driver.find_element(By.CSS_SELECTOR, ".s_ipt")
    # 通过属性
    search_box_css_attr = driver.find_element(By.CSS_SELECTOR, "input[id='kw']")
    print("通过 CSS Selector 定位成功!")
    # 5. 通过 XPath 定位 (同样强大,可以处理复杂结构)
    # 绝对路径 (不推荐,页面结构一变就失效)
    # search_box_xpath_abs = driver.find_element(By.XPATH, "/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input")
    # 相对路径 (推荐)
    search_box_xpath_id = driver.find_element(By.XPATH, "//input[@id='kw']")
    search_box_xpath_class = driver.find_element(By.XPATH, "//input[@class='s_ipt']")
    print("通过 XPath 定位成功!")
finally:
    driver.quit()

定位不到元素怎么办?

  1. 检查等待:页面元素可能还没加载出来,使用显式等待(见第 5 节)。
  2. 检查定位器:在浏览器开发者工具的 Console 中,使用 或 测试你的 CSS/XPath 选择器是否正确。
    • $('#kw') 如果返回元素对象,说明选择器正确。
    • $$('.s_ipt') 如果返回数组,说明正确。
  3. 检查 iframe:如果元素在 <iframe> 标签内,必须先 switch_to.frame() 切换到 iframe 内部才能定位。
  4. 检查元素被遮挡:有时元素本身存在,但被其他元素(如广告、遮罩层)挡住了,导致无法点击。

实战:元素交互

定位到元素后,我们就可以对它进行操作了。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
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")
try:
    # 显式等待,等待搜索框加载出来,最多等待 10 秒
    search_box = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "kw"))
    )
    # 1. 输入文本
    search_box.send_keys("Selenium 教程")
    # 2. 清空文本 (可选)
    # search_box.clear()
    # 3. 点击按钮 (定位“百度一下”按钮)
    search_button = driver.find_element(By.ID, "su")
    search_button.click()
    # 4. 获取元素信息
    # 获取搜索结果区域的文本
    results = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "content_left"))
    )
    print("搜索结果区域文本:", results.text[:100] + "...") # 只打印前100个字符
    # 获取元素的属性
    kw_value = search_box.get_attribute('value')
    print("搜索框中的值是:", kw_value)
finally:
    driver.quit()

处理下拉框

如果遇到 <select> 标签,最好使用 Select 类。

from selenium.webdriver.support.ui import Select
# ... 假设 driver 已经打开了一个有下拉框的页面 ...
# select_element = driver.find_element(By.ID, "select_id")
# select = Select(select_element)
# # 1. 通过索引选择 (从0开始)
# select.select_by_index(1)
# # 2. 通过 value 值选择
# select.select_by_value('option_value_2')
# # 3. 通过可见文本选择
# select.select_by_visible_text('Option 2')

实战:等待策略

这是自动化测试中最重要的概念之一,现代网页大量使用 JavaScript,元素不会立即加载,直接操作会导致 ElementNotInteractableException

强制等待

from time import sleep
driver.get("https://www.slow-loading-website.com")
sleep(5) # 强制等待5秒,不管元素是否加载好
# 然后进行操作
  • 缺点:不智能,无论元素是否加载好,都会等待固定时间,效率低下。

隐式等待

driver.implicitly_wait(10) # 在整个会话期间,所有查找元素的操作最多等待10秒
driver.get("https://www.slow-loading-website.com")
# 如果元素在3秒后加载好了,代码会立即继续执行
# 如果10秒后还没加载好,才会抛出异常
  • 缺点:全局等待,不够灵活,它只作用于 find_element 方法,并且不知道具体哪个元素会加载。

显式等待(强烈推荐)

针对特定元素设置等待条件,直到条件满足或超时。

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver.get("https://www.slow-loading-website.com")
try:
    # 等待最多10秒,直到ID为 "myDynamicElement" 的元素出现
    my_element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
    )
    print("元素已找到!")
    # 等待元素可被点击
    # clickable_element = WebDriverWait(driver, 10).until(
    #     EC.element_to_be_clickable((By.ID, "submit_button"))
    # )
    # clickable_element.click()
    # 等待元素可见
    # visible_element = WebDriverWait(driver, 10).until(
    #     EC.visibility_of_element_located((By.ID, "myDynamicElement"))
    # )
finally:
    driver.quit()
  • 优点:精确、智能、高效,只在你需要的元素上等待,条件明确。
  • 常用 expected_conditions
    • EC.presence_of_element_located: 元素出现在 DOM 中(不一定可见)。
    • EC.visibility_of_element_located: 元素可见(在 DOM 中且 display/visibility 属性不为隐藏)。
    • EC.element_to_be_clickable: 元素可被点击(可见且 enabled)。
    • EC.title_is: 页面标题是指定文本。
    • EC.alert_is_present: 存在弹窗。

实战:多窗口/多标签页处理

当点击一个链接会打开新窗口或新标签页时,需要切换 WebDriver 的焦点。

driver.get("https://www.example.com")
print("当前窗口句柄:", driver.current_window_handle)
# 点击一个会打开新窗口的链接
new_window_link = driver.find_element(By.LINK_TEXT, "Open New Window")
new_window_link.click()
# 获取所有窗口的句柄
all_handles = driver.window_handles
print("所有窗口句柄:", all_handles)
# 切换到新窗口
for handle in all_handles:
    if handle != driver.current_window_handle:
        driver.switch_to.window(handle)
        break
# 现在在新窗口中操作
print("切换后的窗口标题:", driver.title)
# 关闭当前窗口(新窗口)
driver.close()
# 切换回原始窗口
driver.switch_to.window(all_handles[0])
print("回到原始窗口,标题:", driver.title)
# 处理 iframe (如果元素在 iframe 内)
# driver.switch_to.frame("frame_name_or_id")
# ... 在 iframe 内操作 ...
# driver.switch_to.default_content() # 切换回主页面

实战:实战案例 - 自动化登录与信息抓取

让我们来完成一个完整的实战任务:登录 GitHub 并抓取自己仓库的名称

目标网站分析https://github.com/login

  1. 打开登录页面。
  2. 定位用户名输入框 (input[name="login"]) 和密码输入框 (input[name="password"])。
  3. 输入用户名和密码。
  4. 定位并点击登录按钮 (input[type="submit"])。
  5. 登录成功后,导航到你的仓库页面 (https://github.com/YOUR_USERNAME?tab=repositories)。
  6. 定位并抓取所有仓库名称。

完整代码

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
# --- 配置 ---
GITHUB_USERNAME = "你的GitHub用户名"
GITHUB_PASSWORD = "你的GitHub密码"
REPO_URL = f"https://github.com/{GITHUB_USERNAME}?tab=repositories"
def login_and_scrape_repos():
    # 初始化 WebDriver
    service = Service(executable_path='chromedriver.exe') # 如果驱动不在PATH中
    driver = webdriver.Chrome(service=service)
    driver.maximize_window() # 最大化窗口
    try:
        # 1. 打开登录页面
        driver.get("https://github.com/login")
        print("已打开登录页面。")
        # 2. 使用显式等待定位用户名和密码输入框,并输入
        username_field = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.NAME, "login"))
        )
        username_field.send_keys(GITHUB_USERNAME)
        password_field = driver.find_element(By.NAME, "password")
        password_field.send_keys(GITHUB_PASSWORD)
        # 3. 点击登录按钮
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        print("已点击登录按钮。")
        # 4. 等待登录成功,判断是否跳转到了用户主页
        # 我们可以通过检查URL是否包含用户名来判断
        WebDriverWait(driver, 15).until(
            EC.url_contains(GITHUB_USERNAME)
        )
        print("登录成功!当前URL:", driver.current_url)
        # 5. 导航到仓库页面
        driver.get(REPO_URL)
        print("已导航到仓库页面。")
        # 6. 等待仓库列表加载并抓取仓库名
        # 仓库的链接都在 <a> 标签中,class 包含 "repo"
        repo_links = WebDriverWait(driver, 15).until(
            EC.presence_of_all_elements_located((By.CSS_SELECTOR, "a[itemprop='name codeRepository']"))
        )
        print("\n--- 我的仓库 ---")
        repo_names = []
        for link in repo_links:
            repo_name = link.text.strip()
            repo_names.append(repo_name)
            print(f"- {repo_name}")
        return repo_names
    except TimeoutException:
        print("操作超时,可能元素未找到或页面加载缓慢。")
        print("当前页面URL:", driver.current_url)
        print("当前页面标题:", driver.title)
        # 可以在这里截图
        # driver.save_screenshot('error.png')
    except Exception as e:
        print(f"发生错误: {e}")
    finally:
        # 7. 无论成功与否,最后都关闭浏览器
        print("\n操作完成,关闭浏览器。")
        time.sleep(3) # 稍作等待,方便观察
        driver.quit()
if __name__ == "__main__":
    login_and_scrape_repos()

高级技巧与最佳实践

无头模式

在不打开图形界面的情况下运行浏览器,适用于服务器环境。

from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument("--headless") # 无头模式
chrome_options.add_argument("--window-size=1920,1080") # 设置窗口大小
driver = webdriver.Chrome(options=chrome_options)
# ... 后续代码 ...
driver.quit()

使用 Options 配置浏览器

你还可以通过 Options 做很多事情:

chrome_options = Options()
chrome_options.add_argument("--disable-gpu") # 禁用GPU加速
chrome_options.add_argument("--no-sandbox") # 在Linux上可能需要
chrome_options.add_argument("--disable-dev-shm-usage") # 避免/dev/shm不足
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"]) # 隐藏“正在受到自动化软件控制”的提示
chrome_options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=chrome_options)

页面截图与源码保存

# ...
# driver.get("https://example.com")
# driver.save_screenshot('screenshot.png') # 截图
# with open('page_source.html', 'w', encoding='utf-8') as f:
#     f.write(driver.page_source) # 保存页面源码
# ...

使用 try...except 处理异常

自动化脚本健壮性的关键,对于任何可能失败的步骤(如元素定位、点击),都应该用 try...except 包裹。

使用 with 语句管理浏览器

可以更优雅地确保浏览器被关闭。

from selenium import webdriver
class WebDriverManager:
    def __enter__(self):
        self.driver = webdriver.Chrome()
        return self.driver
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.driver.quit()
# 使用方式
with WebDriverManager() as driver:
    driver.get("https://www.baidu.com")
    print(driver.title)
# 退出 with 块后,driver.quit() 会被自动调用

总结与展望

恭喜你!你已经掌握了 Python WebDriver 自动化测试的核心技能。

回顾我们学到的:

  • 环境搭建与脚本运行。
  • 元素定位(ID, CSS, XPath 是重中之重)。
  • 元素交互(点击、输入、获取信息)。
  • 等待策略(显式等待是关键)。
  • 处理多窗口和 iframe。
  • 完整的实战项目。
  • 高级技巧和最佳实践。

下一步可以学习什么?

  1. 数据驱动测试:使用 Excel、CSV 或 JSON 文件来存储测试数据,让脚本更灵活。
  2. Page Object Model (POM):一种设计模式,将页面元素和操作封装成类,让代码更清晰、可维护。
  3. unittest/pytest 框架:使用专业的测试框架来组织和管理你的测试用例,生成测试报告。
  4. Selenium Grid:搭建分布式测试环境,在多台机器上并行运行测试,大幅提升测试效率。
  5. Scrapy + Selenium:Scrapy 擅长抓取静态页面,对于动态页面,可以集成 Selenium 来处理。

WebDriver 是一个强大的工具,希望这篇实战指南能帮助你开启 Web 自动化的大门,祝你学习愉快!

分享:
扫描分享到社交APP
上一篇
下一篇