Skip to content

Web 页面元素 XPath 定位教程

w3school xpath教程

1. XPath 概述

XPath (XML Path Language) 用于在 XML/HTML DOM 中查找节点。浏览器开发者工具 Elements 面板中结构即 DOM。常见用途:RPA 自动化、UI 测试、爬虫定位元素。

两类:

  • 绝对路径:从根节点 html 开始,脆弱:/html/body/div/ul/li[2]/a
  • 相对路径:以任意节点为起点,更常用://div[@class='nav']//a[text()='登录']

1.1 从浏览器中获取元素xpath

在浏览器网页中点击右键,选择检查,后点击到自己想要检查的元素,右键打开面板,选择copy, 再选择copy xpath 即可获取到对应的xpath //*[@id="app"], 也可选择copy full xpath即全部路径 浏览器检查浏览器检查

2. 选择节点的基本语法

  • // 任意层级向下查找
  • / 直接子节点
  • . 当前节点
  • .. 父节点
  • @ 属性
  • * 通配任何标签
  • | 结果合并 (联合选择)

示例:

  • //input[@name='q']
  • //ul/li[1]
  • //div/*/span

3. 常用谓词与索引

谓词 [] 用于过滤:

  • [1] 第一个匹配 (注意 XPath 索引从 1 开始)
  • [last()] 最后一个
  • [position()=2] 第 2 个
  • [@id='kw'] 属性等于
  • [@class] 存在该属性
  • [@class='a b'] 精确匹配(注意 class 顺序与空格)
  • [contains(@class,'btn')] 包含子串
  • [starts-with(@id,'user_')]

示例://table[@id='userTable']//tr[position()>1]

4. 属性与文本匹配

  • 精确文本://a[text()='提交']
  • 文本包含://span[contains(text(),'错误')]
  • normalize-space 去除前后空白://div[normalize-space(text())='首页']
  • 多层文本:使用 . 获取后代纯文本://div[contains(.,'欢迎使用')]

5. 轴 (Axes) 高级查询

语法:轴名称::节点测试

常见轴:

  • ancestor::div 祖先 div
  • ancestor-or-self::
  • parent::
  • child::li
  • following-sibling::li 后面同级
  • preceding-sibling::li 前面同级
  • following::a 文档流中后续任意 a
  • preceding::a
  • descendant::span
  • self::a

组合示例:

  • //label[text()='邮箱']/following-sibling::input
  • //input[@id='pwd']/ancestor::form
  • //li[@class='active']/preceding-sibling::li[last()]

6. 函数精选

  • contains(attr,'x')
  • starts-with(attr,'x')
  • ends-with(attr,'x') (XPath 2.0;浏览器原生多为 1.0,慎用)
  • not(condition)
  • string-length(text())
  • position()
  • last()
  • normalize-space()
  • concat('a','b')
  • matches() (XPath 2.0 正则,Selenium 默认不支持)

示例://input[@type='text' and not(@disabled)]

7. 组合策略

  1. 先锁定局部容器://div[@id='main'] 替代全局搜索
  2. 再缩小范围:添加 class、data-*、角色属性
  3. 使用文本或唯一业务属性 (data-test, aria-label)
  4. 回避易变样式类名 (如自动生成 hash)
  5. 避免纯索引链://div[3]/ul/li[7] 不稳定
  6. 用 contains 拆解多类名:contains(@class,'btn-primary')
  7. 当 id 唯一时优先使用://*[@id='loginBtn']

8. 常见模式示例

  • 根据标签与属性://button[@type='submit']
  • 模糊 class://div[contains(@class,'dialog')]
  • 复合条件://input[@type='password' and @name='pwd']
  • 文本 + 结构://h2[normalize-space(.)='用户列表']/following::table[1]
  • 兄弟节点://td[text()='价格']/following-sibling::td[1]
  • 父子联动://div[@class='item' and .//span[text()='折扣']]
  • 部分动态 id://input[starts-with(@id,'user_')]

9. 针对动态页面

  • 避免绝对路径
  • 不依赖随机数或构建后缀 (如 id='el_169312')
  • 定位稳定语义属性:data-testid, data-role, aria-label
  • 若 class 多变化,优先使用文本或层级关系
  • 可先找外层可识别块再向内://section[@aria-label='搜索']//input[@name='q']

10. 验证与调试

浏览器开发者工具 Console 输入: $ x = $x("//input[@name='q']") (Chrome 支持 $x) $ x[0] 取第一个结果

Selenium 检查: driver.findElement(By.xpath("//a[contains(@href,'/login')]"))

逐步收缩:先 //a 再加属性,再加层级。

11. 性能与可维护性

  • 减少前导 // 全局扫描,优先限定起点://main//a
  • 避免 descendant 深层过宽://div//span 换为具体结构
  • 尽量使用唯一标识,降低结果集合规模
  • 团队统一命名 data-* 测试属性

12. 常见误区

  • class 多值精确匹配失败:class="a b" 需完整匹配或 contains
  • text() 只取直接子文本,嵌套标签需用 . 或 normalize-space(.)
  • 误用索引 0(XPath 起始 1)
  • ends-with 在 XPath 1.0 不可用
  • 过度依赖位置索引易碎
  • 使用 //* 无限制扫描导致性能差

13. 推荐优先级 (稳定性由高到低)

  1. 唯一 id / data-* 属性
  2. 业务语义属性 (aria-label, title, alt)
  3. 稳定文本 (少变化语言)
  4. 局部容器 + 精准属性组合
  5. 层级 + 兄弟关系
  6. 索引 (最后手段)

14. 快速模板

  • 按文本按钮://button[normalize-space(.)='提交']
  • 输入旁标签://label[.='手机']/following::input[1]
  • 表格列单元格://table[@id='t']//tr/td[3]
  • 下拉选项://select[@name='country']/option[@value='CN']
  • 图标按钮://button[.//svg and contains(@class,'close')]

15. 编写步骤建议

  1. 观察 DOM 结构,找最小稳定包裹容器
  2. 判断是否有唯一属性
  3. 选择是否使用文本配合
  4. 评估未来是否变化 (class 风险)
  5. 写出初稿,测试 $x 验证数量
  6. 若返回多个,继续加限定条件
  7. 确认在不同状态 (加载后/展开后) 一致
  8. 归档到定位库并注明意图

16. 快速对照速查

  • //tag
  • //*[@attr='v']
  • //*[contains(@attr,'v')]
  • //*[starts-with(@attr,'v')]
  • //*[text()='v']
  • //*[normalize-space(.)='v']
  • /ancestor::div
  • [position()=n]
  • [last()]
  • [not(@disabled)]

17. 何时不宜用 XPath

  • 简单唯一 id 用 CSS: #loginBtn
  • 仅按 class 且无复杂层级:.btn.primary
  • 性能极敏场景,CSS 选择器通常更快

但 XPath 在:

  • 复杂文本匹配
  • 逆向(找父/祖先)
  • 兄弟关系
  • 组合复杂过滤 更具优势。

18. CSS 对比速览 (参考)

XPath: //div[@id='main']//a[text()='首页'] CSS: #main a:contains('首页') (标准 CSS 不支持文本,需要 JS 扩展;此处说明 XPath 优势)

19. 最终检查清单

  • 唯一性:结果数量 = 1 ?
  • 稳定性:刷新/切换数据仍成立?
  • 可读性:同事可理解意图?
  • 语义性:避免 magic number 索引?
  • 性能:避免全局暴力扫描?

需要更多帮助?

如果您的问题未在此找到答案,请联系技术支持或查看官方文档获取更多帮助。