XPath 教程(2025最新完整版)
XPath(XML Path Language)是一门在 XML 和 HTML 文档中查找信息的查询语言。它是 XSLT、Selenium、Scrapy、lxml、Playwright 等工具的核心定位语言。掌握 XPath,几乎可以在任何网页自动化、爬虫、测试中精准定位元素。
1. 基本概念
| 概念 | 说明 | 示例 |
|---|---|---|
| 节点(Node) | 文档中的每一个部分都是节点 | 元素、属性、文本、注释、文档本身等 |
| 轴(Axis) | 定义从当前节点出发的查找方向 | child、parent、ancestor、following 等 |
| 谓词(Predicate) | 方括号 [] 里的条件,用来过滤节点 | [1]、[@id=’abc’]、[position()>3] |
| 函数 | contains()、starts-with()、text() 等 |
2. 最常用的基本语法(记住这10条就够日常90%场景)
// 从整个文档任意位置开始找(最常用!)
//div → 找所有 div
//div/a → 所有 div 里面的 a(任意层级子孙)
//div//a → 同上,强调可能跨多层
/a → 从根开始的 a(HTML里几乎不用)
//* → 所有元素(通配符)
/ → 从根节点开始(严格一层一层)
//book/title → 所有 book 下的 title(任意深度)
//book[1]/title → 第一个 book 下的 title
//book[last()]/title → 最后一个 book 下的 title
//book[position()<=3] → 前三个 book
3. 通过属性定位(最常用、最稳定)
//input[@id='kw'] → id=kw 的 input
//input[@name='wd']
//a[@class='s_tab']
//div[contains(@class,'login')] → class 包含 login 的 div(推荐!因为class经常多个)
//button[starts-with(@id,'su')] → id 以 su 开头的 button
//a[not(@class)] → 没有 class 属性的 a
//input[@placeholder='搜索']
//img[@src containing 'logo'] → //img[contains(@src,'logo')]
4. 通过文本内容定位(非常实用)
//a[text()='新闻'] → 文本完全等于“新闻”的 a
//a[contain(text(),'新闻')] → 文本包含“新闻”(推荐)
//button[contains(text(),'登录')]
//span[normalize-space()=' 登 录 '] → 去掉前后空格和换行的文本匹配(超实用!)
5. 组合条件(and、or)
//input[@type='text' and @name='wd']
//div[contains(@class,'item') and contains(text(),'手机')]
//a[@href='https://www.baidu.com' or @target='_blank']
6. 常用轴(Axis)写法
| 轴 | 含义 | 示例 |
|---|---|---|
| . | 当前节点 | .//div |
| .. | 父节点 | ..//div |
| / | 根节点 | /html/body/div |
| ancestor:: | 所有祖先节点 | //div/ancestor::body |
| ancestor-or-self:: | 所有祖先+自己 | |
| parent:: | 直接父节点 | //span/parent::div |
| child:: | 直接子节点 | //ul/child::li |
| descendant:: | 所有后代 | //div/descendant::a |
| descendant-or-self:: | 所有后代+自己 | //div//a 的本质 |
| following:: | 当前节点之后所有节点(同层+下层) | //input[@id=’kw’]/following::input[1] → 下一个 input |
| following-sibling:: | 同层后面的兄弟节点 | //li[3]/following-sibling::li |
| preceding:: | 当前节点之前所有节点 | |
| preceding-sibling:: | 同层前面的兄弟节点 |
7. 实战中最常用的20条 XPath(直接复制就行)
1. 输入框通用
//input[@type='text' or @type='password' or not(@type)]
2. 任意可点击按钮
//button | //a[contains(@class,'btn')] | //input[@type='submit' or @type='button']
3. 包含某个文本的任意标签
//*[contains(text(),'立即注册')]
4. 精准文本(去空格)
//*[@normalize-space(.)='登录']
5. 找父元素(超常用!)
.//当前元素/.. 或 .//当前元素/parent::*
6. 找包含某个元素的父级
//div[.//span[text()='价格']]/parent::*
7. 第n个元素
(//div[@class='item'])[3] → 关键加括号!第3个
8. 倒数第n个
(//div[@class='item'])[last()-1]
9. 动态id/class(包含关键词)
//*[@id[contains(.,'login')]]
//div[contains(@class,'ant-') and contains(@class,'row')]
10. 找图片
//img[contains(@src,'.jpg') or contains(@src,'.png')]
11. iframe 里的元素(先切换iframe再用)
//iframe[@id='if']/following-sibling::iframe//input
12. shadow DOM(现代前端)—— XPath 无法直接穿透 shadow DOM,需要用 JS
13. 表格第2行第3列
//table//tr[2]/td[3]
14. 列表中包含“手机”的那一项
//li[contains(.,'手机')]
15. 任意层级包含某个类的元素
//descendant::*[contains(@class,'active')]
16. 没有被禁用的输入框
//input[not(@disabled)]
17. 可见元素(简单写法)
//*[not(contains(@style,'display:none')) and not(contains(@style,'hidden'))]
18. 获取属性值(在Scrapy/lxml中)
//a[@class='title']/@href
19. 获取文本(去空格)
//div[@class='price']/normalize-space(.)
20. 最强组合:文本+属性
//span[contains(text(),'总价')]/following-sibling::span//span[@class='num']
8. Chrome 浏览器快速测试 XPath(2025最新方法)
- 打开开发者工具(F12)
- 按 Ctrl + F(在 Elements 面板里)
- 直接输入 XPath,立即高亮匹配的元素
- $x(“你的xpath”) 在 Console 里也能测试
$x("//a[contains(text(),'新闻')]")
9. 常见坑 & 最佳实践
| 坑 | 正确做法 |
|---|---|
| 用 //div[1] | 用 (//div)[1] 括号优先! |
| 直接用 text()=’ 登录 ‘ | 用 normalize-space()=’登录’ 或 contains |
| class 完全匹配 @class=’a b c’ | 用 contains(@class,’b’) 或 @class[contains(.,’b’)] |
| 动态生成的 id | 用 contains、starts-with 或父子关系定位 |
| 多个相同 XPath | 用 [position()=n] 或 [last()] 区分 |
10. 快速记忆口诀(背下来就无敌)
“双斜杠到处找,属性@方括号包,
文本contains包,位置加括号,
父找parent或两点,兄弟following,
去空格normalize-space最重要!”
掌握上面内容,你已经超过90%的爬虫/自动化测试工程师了!
有具体网页定位问题,直接把HTML片段发给我,我帮你写最稳的XPath。开始练习吧!