XPath的谓词是嵌入在方括号中的表达式,用于对节点集进行条件过滤,只有满足谓词条件的节点才会被保留到最终结果中,是XPath实现精准定位的核心手段。

XPath谓词的基本语法
谓词紧跟在节点测试之后,用方括号包裹,基本格式为节点测试[谓词条件]。谓词中的条件可以是数值、比较表达式、函数调用等多种形式,XPath解析器会对当前节点集的每个节点执行谓词条件判断,返回结果为真则保留该节点。
例如要筛选所有class属性为active的div节点,表达式可以写为:
//div[@class='active']
这里的@class='active'就是谓词条件,@用于选取属性,整个表达式的含义是选取所有div节点中class属性等于active的节点。
常见谓词使用场景
1. 基于属性值筛选
通过属性值筛选是最常用的谓词场景,除了等于判断,还支持不等于、包含等逻辑。
- 筛选id不等于header的div节点:
//div[@id!='header'] - 筛选class属性包含btn的button节点:
//button[contains(@class,'btn')] - 筛选href属性以https开头的a节点:
//a[starts-with(@href,'https')]
2. 基于位置筛选
谓词支持位置索引,XPath的索引从1开始,常用位置相关的谓词如下:
- 选取第一个p节点:
//p[1] - 选取前两个li节点:
//li[position()<=2] - 选取最后一个tr节点:
//tr[last()] - 选取倒数第二个td节点:
//td[last()-1]
3. 基于节点内容筛选
可以通过文本内容或者子节点数量作为谓词条件:
- 筛选文本内容为提交的button节点:
//button[text()='提交'] - 筛选包含span子节点的div节点:
//div[span] - 筛选子节点数量大于3的ul节点:
//ul[count(li)>3]
4. 组合条件筛选
谓词中可以使用and、or运算符组合多个条件:
- 筛选class为active且id为user的div节点:
//div[@class='active' and @id='user'] - 筛选type为text或者type为password的input节点:
//input[@type='text' or @type='password']
实际代码示例
假设我们有以下HTML片段:
<div class="container">
<ul id="list">
<li class="item" data-id="1">商品1</li>
<li class="item active" data-id="2">商品2</li>
<li class="item" data-id="3">商品3</li>
<li class="item" data-id="4">商品4</li>
</ul>
<input type="text" placeholder="请输入内容" />
<input type="password" placeholder="请输入密码" />
<a href="https://ipipp.com">跳转链接</a>
</div>
对应的XPath谓词筛选示例如下:
from lxml import etree
# 解析HTML
html = etree.parse("test.html", etree.HTMLParser())
# 筛选class包含active的li节点
active_items = html.xpath('//li[contains(@class,"active")]')
print("激活的商品:", [item.text for item in active_items])
# 筛选前两个li节点
first_two_items = html.xpath('//li[position()<=2]')
print("前两个商品:", [item.text for item in first_two_items])
# 筛选type为password的input节点
password_input = html.xpath('//input[@type="password"]')
print("密码输入框数量:", len(password_input))
# 筛选href以https开头的a节点
https_links = html.xpath('//a[starts-with(@href,"https")]')
print("https链接文本:", [link.text for link in https_links])
注意事项
- 谓词中的比较运算符
<、>在XML/HTML文档中需要转义为<、>,避免被解析为标签。 - 字符串比较时需要注意大小写,XPath默认是大小写敏感的,如果需要忽略大小写可以结合translate函数处理。
- 多个谓词可以连续使用,例如
//li[@class='item'][1]表示先筛选class为item的li节点,再取第一个节点,和//li[1][@class='item']的筛选逻辑一致。