目录
- 什么是 WebDriver?为什么选择它?
- 环境准备
- 安装 Python
- 安装 Selenium 库
- 安装浏览器驱动
- 第一个 WebDriver 脚本:打开网页
- 核心实战:元素定位
- 什么是元素?
- 8 种定位方式详解(附实战案例)
- 定不到元素怎么办?(常见问题与解决方案)
- 实战:元素交互
- 点击、输入、清空、获取文本/属性
- 处下拉框
- 处弹窗
- 实战:等待策略
- 强制等待
- 隐式等待
- 显式等待(重点)
- 实战:多窗口/多标签页处理
- 实战:实战案例:自动化登录与信息抓取
- 目标网站分析
- 编写完整代码
- 代码讲解
- 高级技巧与最佳实践
- 无头模式
- 使用
Options配置浏览器 - 页面截图与源码保存
- 使用
try...except处理异常 - 使用
with语句管理浏览器
- 总结与展望
什么是 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 --version
如果没有安装,请从 Python 官网 下载并安装。
安装 Selenium 库
打开终端/命令行,使用 pip 安装:
pip install selenium
安装浏览器驱动
WebDriver 需要一个“翻译官”来告诉浏览器该做什么,这个“翻译官”浏览器驱动,你需要为你的浏览器下载对应的驱动。
以 Chrome 为例(最常用):

- 确认 Chrome 版本:打开 Chrome 浏览器 -> 设置 -> Chrome,记下你的 Chrome 版本号(
0.6312.86)。 - 下载驱动:
- 访问 Chrome for Testing availability (Google 提供的官方镜像)。
- 找到与你 Chrome 版本号最接近的
chromedriver。 - 根据你的操作系统下载对应的文件(
chromedriver-win64.zip)。
- 配置驱动路径:
- 方法一(推荐,最简单):将下载的
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 语法 | 描述 | 优先级 |
|---|---|---|---|
| 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()
定位不到元素怎么办?
- 检查等待:页面元素可能还没加载出来,使用显式等待(见第 5 节)。
- 检查定位器:在浏览器开发者工具的 Console 中,使用 或 测试你的 CSS/XPath 选择器是否正确。
$('#kw')如果返回元素对象,说明选择器正确。$$('.s_ipt')如果返回数组,说明正确。
- 检查 iframe:如果元素在
<iframe>标签内,必须先switch_to.frame()切换到 iframe 内部才能定位。 - 检查元素被遮挡:有时元素本身存在,但被其他元素(如广告、遮罩层)挡住了,导致无法点击。
实战:元素交互
定位到元素后,我们就可以对它进行操作了。
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
- 打开登录页面。
- 定位用户名输入框 (
input[name="login"]) 和密码输入框 (input[name="password"])。 - 输入用户名和密码。
- 定位并点击登录按钮 (
input[type="submit"])。 - 登录成功后,导航到你的仓库页面 (
https://github.com/YOUR_USERNAME?tab=repositories)。 - 定位并抓取所有仓库名称。
完整代码
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。
- 完整的实战项目。
- 高级技巧和最佳实践。
下一步可以学习什么?
- 数据驱动测试:使用 Excel、CSV 或 JSON 文件来存储测试数据,让脚本更灵活。
- Page Object Model (POM):一种设计模式,将页面元素和操作封装成类,让代码更清晰、可维护。
- unittest/pytest 框架:使用专业的测试框架来组织和管理你的测试用例,生成测试报告。
- Selenium Grid:搭建分布式测试环境,在多台机器上并行运行测试,大幅提升测试效率。
- Scrapy + Selenium:Scrapy 擅长抓取静态页面,对于动态页面,可以集成 Selenium 来处理。
WebDriver 是一个强大的工具,希望这篇实战指南能帮助你开启 Web 自动化的大门,祝你学习愉快!
