← 返回学习中心ARC LAB / LEARNING NOTES

Python 专区

Python Selenium

在本地练习页中定位、输入、点击、等待和断言,生成真实截图。

展开本篇目录

一、为什么学习 Selenium?

Selenium WebDriver 通过真实浏览器验证页面交互:定位元素、输入、点击、等待状态和截屏。它适合网页自动化测试,不是单纯的 HTTP 客户端,也不应该把“点击成功”当作业务已完成。

先修 Python、HTML 基础和 CSS 选择器。路线:启动浏览器 → 打开自己的练习页 → 定位 → 操作 → 等待 → 断言 → 清理。本文只操作本地教学页面。

Python 通过 WebDriver 控制浏览器,定位 DOM 并等待页面状态后进行断言

二、环境与驱动

python -m pip install selenium

还需要 Chrome 等支持的浏览器与兼容驱动。现代 Selenium 可以通过 Selenium Manager 管理驱动;首次运行可能需要联网下载,代理、网络或写入权限也可能导致失败。离线环境可提前准备兼容驱动,并显式设置 Service 路径。

不要把浏览器版本与驱动问题误判为 Python 语法问题,也不要从不明来源下载可执行驱动。本篇完整脚本支持 --driver 与 --chrome 显式指定路径。

三、先用一个最小练习页

下载 selenium_lab.html · 下载 selenium_demo.py

将两个文件放在同一目录:

python selenium_demo.py --page selenium_lab.html --output results

页面只有姓名输入框和 Greet 按钮。点击后先显示 Loading,约 400ms 后更新结果,专门用于练习显式等待。无需账号、Token 或第三方网站。

自动化运行前的真实浏览器截图,输入框为空,提示等待输入

四、启动、打开与释放浏览器

from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--window-size=1100,780")
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com") # 接口示意;完整练习用本地页面
print(driver.title)
finally:
driver.quit()

headless 表示无可见窗口,不表示不使用真实浏览器,也不保证与所有有界面场景完全相同。quit() 结束会话并清理浏览器;只调用 close 通常仅关闭当前窗口。

本地文件使用 Path(...).resolve().as_uri() 转成正确的 file URI;不要手工拼接不同系统的路径分隔符。

五、定位元素:选择稳定的接口

from selenium.webdriver.common.by import By
field = driver.find_element(By.ID, "name")
button = driver.find_element(By.CSS_SELECTOR, "button#greet")
定位方式 例子 建议
ID By.ID, "name" 有稳定唯一 ID 时优先
CSS input[name='email'] 通常简洁、可组合
XPath //button[@id='greet'] 需要结构关系时使用
链接文字 可见链接文本 会受语言与文案变化影响

避免依赖随机 class 或从 body 开始的超长绝对 XPath。开发自己的产品时,可以约定稳定的测试属性。find_element 找不到会抛异常,find_elements 找不到返回空列表。

六、输入、点击与断言

field.clear()
field.send_keys("ArcLab")
button.click()

不能马上假设状态已经更新。输入值通常通过 get_attribute("value") 获取;.text 通常用于可见文本,不能指望它读取输入框 value。

点击后被遮挡时,检查弹层、滚动位置和禁用状态。直接用 JavaScript 强制触发可能绕开真实用户无法点击的问题,不应作为默认“修好测试”的办法。

七、显式等待:等条件而不是猜时间

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
field = wait.until(EC.visibility_of_element_located((By.ID, "name")))
wait.until(EC.element_to_be_clickable((By.ID, "greet"))).click()
wait.until(EC.text_to_be_present_in_element((By.ID,"status"),"Hello, ArcLab!"))
assert driver.find_element(By.ID,"status").text == "Hello, ArcLab!"

这段假设已输入 ArcLab。存在于 DOM、可见、可点击、结果已更新是不同条件。不要用 sleep(10) 代替业务条件,也避免混合大量隐式与显式等待,导致超时难以预测。

实际运行后的浏览器截图:输入 ArcLab,等待后显示 Hello, ArcLab!

配套脚本继续清空姓名,再验证 Please enter a name,覆盖正常和空输入两条路径。

八、动态页面与 stale element

页面更新可能替换原来的 DOM 节点,旧 WebElement 引用随之失效。收到 StaleElementReferenceException 时,应理解是哪次更新替换了节点,再按稳定定位器重新查找,而不是无限重试整个流程。

对动态列表,先等待目标状态,再重新获取元素。若点击只是开始下载或异步任务,应等待完成标记、文件状态或服务端结果,而不是仅凭按钮已消失判成功。

九、窗口、iframe、弹窗与 Select

  • iframe 中的元素需要先切换 driver.switch_to.frame(...),完成后 default_content()。
  • 新窗口通过 window_handles 与 switch_to.window 管理,不要假定顺序永远固定。
  • 浏览器原生 alert 与网页 HTML 弹层不同,前者使用 alert 接口。
  • 标准 <select> 可用 Selenium 的 Select 辅助类;自绘下拉框不能直接套用它。

这些是后续进阶主题;首次练习先把单页面中的状态和断言做好。

十、截图、失败证据与测试独立性

driver.save_screenshot("result.png")

截图是辅助证据,仍需断言文本、URL 或状态。不要把包含账号、Cookie、个人数据的截图直接提交公共仓库。不同字体、系统和浏览器版本可能导致像素差异,视觉对比应设置合理环境与容差。

每个测试应能独立建立前置条件,不依赖另一个测试先登录或先创建记录。批量测试可进一步用测试框架与 Page Object 组织,但不要一开始写庞大的封装层。

十一、完整实验与故障排查

完整脚本运行成功输出:

Passed: greeting, explicit wait, empty-input validation and screenshots.

会保存 before/after 两张截图,并在 finally 中退出浏览器。首次驱动下载不属于网页业务等待,失败时先区分环境初始化和页面断言。

问题 检查顺序
驱动初始化失败 浏览器安装、版本、网络、驱动路径
找不到元素 URL、选择器、iframe、是否尚未加载
点击被遮挡 弹层、滚动、元素状态
等待超时 条件是否正确、页面是否有报错
旧元素失效 页面重绘后重新定位
运行结束残留进程 是否在 finally 中 quit

十二、练习与学习资料

  1. 将姓名改为其他值,断言完整结果而不仅是包含 Hello。
  2. 验证空输入路径,确认零长度字符串与空白字符串都被处理。
  3. 把教学页延时改为 1200ms,显式等待仍应成功,无需调整 sleep。
  4. 故意改错 ID,观察异常,保存失败页面和日志。
  5. 小项目:为自己的静态网站实现导航、语言切换和手机菜单测试,不操作未经授权的账号或绕过验证码。
← 继续探索学习路径反馈问题 ↗