元素定位演示 · XPath 定位

系统学习 By.XPATH 的核心语法、实操示例与最佳实践

首页 定位导航

By.XPATH 定位导读

XPath(XML Path Language)是 W3C 定义的文档树导航标准,也是 Selenium 中功能最强大、最灵活的元素定位方式。它通过路径表达式遍历 HTML DOM 树的任意方向(父、子、兄弟、祖先、后代),结合属性匹配(@id/@name/@class)、文本函数(text()/contains())、位置索引与逻辑运算符(and/or)实现精准定位。理论上页面中任何元素都能用 XPath 定位,但需注意其依赖 DOM 层级结构,页面变动时可能失效,建议优先使用相对路径(//)而非绝对路径。

By.XPATH 快速入门
掌握核心语法与定位策略
语法示例
find_element / find_elements 用法
实操练习
交互式练习区实时反馈
By.XPATH

⑦ XPath 定位

XML 路径语言,支持路径/属性/文本/轴等复杂定位
XPath 定位语法:
单个元素 (find_element)
driver.find_element(By.XPATH, "/html/body/div[1]/header/h1")(① 绝对路径
🗂️ 绝对路径:从根到目标,一步不差
XPath 里以 / 开头就是绝对路径,从 /html 根节点出发,逐层下钻到目标元素:
/html/body/div[1]/form[2]/div[3]/input
① /html → 根节点
② /body → body 直接子
③ /div[1] → 第 1 个 div 直接子
④ /form[2] → 第 2 个 form 直接子
⑤ /div[3] → 第 3 个 div 直接子
⑥ /input → 目标元素
⚠️ 绝对路径的致命问题:
• DOM 结构一变(中间加个 div 或序号变了),整条路径作废
• 不同浏览器渲染可能微调 DOM 层级
• 前端框架(React/Vue/Angular)渲染时结构不稳定
• 实战中 95%+ 不用绝对路径,除非页面结构完全固定
)
driver.find_element(By.XPATH, "//input")(② 相对路径
📘 相对路径(//)—— 从当前节点全局搜索
📖 相对路径是什么?
以 // 开头,表示"从当前节点往任意深度跳",不要求从根逐层下钻。相当于"全局搜索",找到第一个匹配就返回。
//input → 页面第一个 input
//form//input → form 下任意深度的 input
//*[@id='userName'] → 任意标签 id=userName
💪 相对路径的优势(为什么 95%+ 用它)
✅ 抗 DOM 变化:中间加/减 div 不影响定位
✅ 语法简洁://input 仅需标签名即可定位,无需逐层书写完整 DOM 路径
✅ 浏览器兼容:不受不同浏览器渲染层级差异影响
✅ 框架友好:React/Vue 动态渲染也不怕
⚠️ 使用要点 & 常见陷阱
① // 搜索全页面://input 取第一个,页面多个 input 时要加索引或属性
② 性能略差:// 比 / 慢(全局遍历),但现代浏览器差异可忽略
③ 别嵌套 //://div//span//a 虽然合法但可读性差,建议用轴或属性
④ 多用属性限定://input[@id='x'] 比 //input 稳定得多
⑤ contains 别乱用://div[contains(@class,'btn')] 可能匹配多个,配合 and 缩小范围
💡 实战最佳实践://tag[@id='xxx'] 或 //button[text()='提交']
🔀 // 和 / 混用 —— 核心规则
XPath 里 // 和 / 可以在同一条表达式里混用!每一步独立选择层级方式:
示例:
/html/body//form[@id='x']/div//input[@name='y']
↑ 根 ↑ 跳层 ↑ 直接子 ↑ 跳层
① /html/body 从根逐层下到 body(绝对)
② //form 从 body 任意深度跳层找 form(相对)
③ /div form 的直接子 div(逐层)
④ //input div 下任意深度跳层找 input(相对)
✅ 不是"要么全 // 要么全 /",每一段步长自由选择。
)
driver.find_element(By.XPATH, "(//input)[2]")(③ 元素索引
🔢 元素索引 (//标签)[n]
当 //标签 匹配多个元素时,用 [n] 取第 n 个,下标从 1 开始:
(//input)[1] → 第一个 input(等同 //input)
(//input)[2] → 第二个 input
(//input)[last()] → 最后一个 input
✅ 注意是 圆括号 括住 //标签 再加 [n],不是 //标签[n](后者含义不同)。
⚠️ (//input)[0] 是错的!XPath 下标从 1 开始,不是 0。
⚠️ 索引在动态页面不稳定,DOM 顺序一变就取错元素。
)
driver.find_element(By.XPATH, "//input[@id='userName']")(④ 属性
🏷️ 属性选择:最稳定的定位方式
用 [@属性='值'] 筛选元素,实战首选:
//input[@id='userName'] → id 最稳定,优先用
//input[@name='email'] → name 次之
//input[@type='password'] → type 也可
//button[@class='primary'] → class 不太稳定(多 class 问题)
✅ 优先级:@id > @name > @data-* > @type > @class
⚠️ class 多值时 [@class='btn primary'] 要全写,漏一个就匹配不到 → 用 contains。
⚠️ @id 在 Vue/React 动态渲染时可能变化(如 el-123),注意检查。
)
driver.find_element(By.XPATH, "//div[contains(@class,'demo')]")(⑤ 模糊属性值
🔤 模糊属性值:starts-with + contains
a. starts-with(@属性, '前缀'):匹配属性值以某字符串开头
//input[starts-with(@type,'pass')] → type="password" 能匹配
//div[starts-with(@id,'el-')] → Vue 动态 id 通用匹配
b. contains(@属性, '关键字'):匹配属性值包含某字符串(最常用)
//div[contains(@class,'btn')] → 能匹配 class="btn btn-primary"
//a[contains(@href,'selenium')] → href 里有 selenium 的链接
//input[contains(@placeholder,'用户名')] → placeholder 包含关键字
✅ contains 比 starts-with 更灵活,是实战首选。
✅ contains(., '文字') 还能匹配元素的文本内容。
⚠️ 两个函数都大小写敏感,参数必须加引号。
⚠️ contains 可能匹配多个元素,建议配合 and 缩小范围。
⚠️ XPath 函数名大小写敏感:starts-with 不能写成 Starts-With。
)
driver.find_element(By.XPATH, "//button[normalize-space()='提交表单']")(⑥ 文本匹配
📝 文本匹配:精确 + 部分(contains)
① 精确匹配:[text()='xxx'] 或 [normalize-space()='xxx']
//button[text()='提交'] → 精确匹配
//button[normalize-space()='提交表单'] → 忽略前后空格,推荐
② 部分匹配:[contains(text(),'关键字')] — 文本包含某关键字即可
//a[contains(text(),'登录')] → 包含"登录"就能匹配
//button[contains(., '保存')] → 匹配整个节点内(含子元素)文本
//span[contains(normalize-space(), '搜索')] → trim 后再判断包含
✅ 部分匹配更灵活:文案变了但关键字保留的场景(如"立即登录"→"登录")。
✅ contains(., '文字') 用 .(当前节点)比 text() 范围更广——连子元素里的文本也能匹配。
⚠️ text() 只匹配直接子文本节点,子元素里的文本不算;用 . 可覆盖。
⚠️ contains 部分匹配可能命中多个元素,建议配合属性或索引缩小范围。
⚠️ 文本会变!国际化、A/B 测试都可能改文案,别在关键路径上依赖文本匹配。
)
driver.find_element(By.XPATH, "//div[@class='form-grid']/div[last()]")(⑦ 函数条件匹配
🧮 XPath 内置函数
XPath 提供多种内置函数,最常用的几个:
[last()] → 取最后一个同级元素
[position()=n] → 取第 n 个同级(等同 [n])
[last()-1] → 取倒数第二个
string-length(@id) → 属性值的字符串长度
ceiling()/floor() → 向上/向下取整(少用)
✅ last() 特别实用——动态列表中取最后一项很方便。
⚠️ position() 依赖当前节点集顺序,复杂 XPath 中可能不符合预期。
⚠️ XPath 不支持自定义函数,只能用内置的。
)
driver.find_element(By.XPATH, "//*[@name='email' and @type='text']")(⑧ 逻辑运算符
🔗 and / or / not:多条件组合
用 and / or / not() 组合多个筛选条件:
//input[@name='email' and @type='text'] → 同时满足
//input[@type='text' or @type='password'] → 任一满足
//input[not(@disabled)] → 未禁用的 input
✅ and 是实战中最常用的——给 contains 加第二条件缩小范围。
⚠️ 不要用 && / ||,XPath 里是 and / or(英文单词)。
⚠️ not() 是函数不是运算符:[not(@disabled)],不能写 [!@disabled]。
)
driver.find_element(By.XPATH, "//label/following-sibling::input")(⑨ 轴定位
🧭 轴定位:全方向导航
轴(Axis)让你从当前元素向任意方向导航:
//label/following-sibling::input → label 后面的 input 兄弟
//input/preceding-sibling::label → input 前面的 label 兄弟
//td/ancestor::tr → td 的祖先 tr 行
//div/parent::form → div 的父 form
✅ following-sibling / preceding-sibling 最实用——处理表单项(label + input)绝配。
⚠️ 轴是 XPath 最强大但最少用的功能——90% 的场景 // + 属性就能搞定。
⚠️ 轴语法:节点/轴名::tag,双冒号 :: 别写成单冒号。
)
📘 两种写法模式:
基础写法(9 种纯技法):每条 XPath 只展示一种技法,便于理解;
复杂写法(多技法混合):把多种技法混在一条里(// + / + contains + and + 轴 + 函数),实战中 90%+ 的定位都这样写!
点击上面的「基础 XPath 定位」和「复杂 XPath 定位」按钮对比看效果。
多个元素 (find_elements) — 语法完全相同,返回 List 而非单个 WebElement
driver.find_elements(By.XPATH, "/html/body/div[1]/header/h1")(① 绝对路径)
driver.find_elements(By.XPATH, "//input")(② 相对路径)
driver.find_elements(By.XPATH, "(//input)[2]")(③ 元素索引)
driver.find_elements(By.XPATH, "//input[@id='userName']")(④ 属性)
driver.find_elements(By.XPATH, "//div[contains(@class,'demo')]")(⑤ 模糊属性值)
driver.find_elements(By.XPATH, "//button[normalize-space()='提交表单']")(⑥ 文本匹配)
driver.find_elements(By.XPATH, "//div[@class='form-grid']/div[last()]")(⑦ 函数条件匹配)
driver.find_elements(By.XPATH, "//*[@name='email' and @type='text']")(⑧ 逻辑运算符)
driver.find_elements(By.XPATH, "//label/following-sibling::input")(⑨ 轴定位)
特点:功能最强大,支持路径 / 属性 / 文本 / 函数 / 轴 / 逻辑运算符等复杂定位,是 Selenium 中最灵活的定位方式;但语法较复杂、不同浏览器渲染差异可能导致绝对路径失效,实战推荐相对路径 // + 属性组合。
实操练习:By.XPATH → 查看 Selenium 代码与执行结果
练习表单:form#demoXpathForm(仅用于 loc-practice-area)

示例表单(id="xpathForm")

XPath 实战技巧
  • 优先使用 相对路径 //,不推荐用 /html/body/div... 绝对路径。
  • 组合 @id/@name/@class/@type 等属性,多属性 and 更稳定。
  • 文本匹配:text()='xxx' 或 contains(text(),'xxx')。
  • 索引:(//...)[n],XPath 下标从 1 开始。
定位后操作效果展示区域
本区域用于展示:使用 Selenium / JS 定位到上方元素后,执行「点击 / 输入 / 提交」等操作的真实反馈结果。

关于我们

Python 自动化测试学习平台是一个面向软件测试工程师、开发人员及在校学生的交互式在线学习平台,专注于 Selenium WebDriver 与 Python unittest 自动化测试技能的教学与实践。

我们以"理论 + 实战 + 可交互演示"为核心特色,将八种常规元素定位和Javascript定位、元素操作、自动化测试工具、单元测试、测试模型等知识体系拆分为模块化课程,每个模块都配有可点击、可输入、可运行的模拟练习页面。

平台致力于降低自动化测试的入门门槛,让学习者从"看懂代码"到"动手实操",逐步掌握企业级自动化测试框架的设计与落地能力。

联系方式

📧邮箱:lq@selenium-auto-test.com

📞电话:0755-12345678

📍地址:深圳

💬微信公众号:Selenium自动化测试

🐙GitHub:github.com/selenium-auto-test

免责声明

1. 本平台所有示例代码、演示页面及教程内容均仅供学习交流使用,不构成任何商业推广或技术服务承诺。

2. 平台中的 Selenium API 描述、Python 语法说明均以官方文档为准,如有版本差异请以对应官方文档为准。

3. 学习者在实际项目中应用平台所学内容时,应结合自身项目环境进行充分测试,本平台不对因直接使用示例代码而产生的任何直接或间接损失承担责任。

4. 本平台所引用的第三方库(Selenium、ChromeDriver、unittest 等)版权归其各自作者及维护者所有。

5. 如涉及版权问题或内容建议,请及时通过联系方式与我们沟通,我们将第一时间处理。