XPath全称为XML Path Language,是一种用来在XML和HTML文档中导航和查找信息的语言,核心是通过路径表达式来定位文档中的节点,不管是做网页数据抓取还是配置文件解析,都能发挥很大作用。

XPath基础概念
XPath把XML或HTML文档看作一个树形结构,文档中的每个元素、属性、文本都是一个节点,常见的节点类型有以下几种:
- 元素节点:对应文档中的标签,比如<div>、<p>都是元素节点
- 属性节点:对应元素的属性,比如<div class="content">中的class就是属性节点
- 文本节点:对应元素内部的文本内容,比如<p>测试文本</p>中的测试文本就是文本节点
常用XPath路径表达式
路径表达式是XPath的核心,下面是最常用的几种表达式写法:
| 表达式 | 说明 | 示例 |
|---|---|---|
| / | 从根节点开始选取 | /html/body/div 选取根节点下html元素内的body元素下的所有div子节点 |
| // | 从当前节点选取所有后代节点,不管位置 | //div 选取文档中所有的div节点 |
| . | 选取当前节点 | ./p 选取当前节点下的p子节点 |
| .. | 选取当前节点的父节点 | //p/.. 选取所有p节点的父节点 |
| @ | 选取属性 | //div/@class 选取所有div节点的class属性 |
| [] | 添加筛选条件 | //div[1] 选取第一个div节点 |
谓语筛选用法
谓语用来查找特定条件的节点,放在方括号中,常用的谓语写法有:
- //div[@class="test"]:选取所有class属性为test的div节点
- //p[contains(text(), "内容")]:选取文本内容包含内容的p节点
- //ul/li[last()]:选取每个ul下的最后一个li节点
- //div[@id="main"]//p[position()<3]:选取id为main的div下前两个p节点
通配符与多路径选择
XPath还支持通配符和多个路径组合选择:
- 通配符*:匹配任意元素节点,比如//* 选取文档中所有元素节点
- 通配符@*:匹配任意属性节点,比如//div[@*] 选取所有带属性的div节点
- 多路径选择|:可以同时选取多个路径的节点,比如//div|//p 选取所有div和p节点
实战代码示例
下面用Python的lxml库演示XPath的实际用法,首先准备一段测试用的HTML内容:
from lxml import etree
# 测试用的HTML内容
html_content = """
<html>
<body>
<div id="main">
<p class="title">XPath教程</p>
<ul>
<li>基础语法</li>
<li>路径表达式</li>
<li>实战案例</li>
</ul>
<p class="content">XPath是常用的解析工具</p>
</div>
</body>
</html>
"""
# 解析HTML
html = etree.HTML(html_content)
# 1. 选取所有p节点
p_nodes = html.xpath("//p")
print("所有p节点文本:", [node.text for node in p_nodes])
# 2. 选取class为title的p节点
title_node = html.xpath("//p[@class='title']")
print("标题节点文本:", title_node[0].text if title_node else None)
# 3. 选取ul下所有li节点的文本
li_texts = html.xpath("//ul/li/text()")
print("li节点文本列表:", li_texts)
# 4. 选取id为main的div下第一个p节点的class属性
first_p_class = html.xpath("//div[@id='main']/p[1]/@class")
print("第一个p的class属性:", first_p_class[0] if first_p_class else None)
运行上面的代码,就能得到对应的节点内容,大家可以把测试内容换成自己需要解析的网页源码,调整路径表达式来提取目标内容。
注意事项
- 路径表达式中的索引是从1开始的,和编程里的数组从0开始不同,比如第一个节点是[1]不是[0]
- 如果路径中包含特殊字符,比如class属性值有空格,需要用contains函数或者转义处理
- 不同解析库对XPath的支持略有差异,使用时可以先测试基础表达式是否生效