0

0

XPath的|运算符如何合并多个结果集?

星降

星降

发布时间:2025-08-15 10:38:02

|

217人浏览过

|

来源于php中文网

原创

xpath中的|运算符是节点集联合操作符,用于将多个xpath表达式匹配的节点集合并为一个无重复的集合,例如//h1 | //h2可同时选取所有h1和h2元素,它操作的是结果集的并集,而不同于and/or这类在谓词中对单个节点进行条件判断的布尔操作符,因此|适用于跨结构收集分散但逻辑相关的数据,在处理页面布局不一致、a/b测试或多路径信息聚合时尤为高效,但需注意其可能带来的性能开销、结果顺序不确定性及调试复杂性,合理使用可显著提升数据抓取的灵活性与鲁棒性。

XPath的|运算符如何合并多个结果集?

XPath中的

|
运算符,简单来说,它就像是数据抓取领域的“或”门,但它操作的不是布尔值,而是节点集。它的核心功能就是将多个XPath表达式各自选中的节点集合并成一个单一的、不含重复项的节点集。这在处理页面结构不规则或需要从不同位置抓取相关信息时,简直是神器。

解决方案

XPath的

|
运算符,正式名称是“联合运算符”(Union Operator),它的作用是将两个或多个XPath表达式所匹配到的节点集进行合并。这个合并过程会确保最终的结果集中不包含重复的节点,即使某个节点被多个表达式匹配到,它也只会在最终结果中出现一次。这对于我们从网页中提取数据时,需要同时关注多个可能位置或类型的元素时,提供了极大的便利。

举个例子,假设你想抓取一个页面上所有的标题,但这些标题可能分散在

甚至

标签里。你完全可以用
//h1 | //h2 | //h3
这样一个简洁的表达式,一次性获取所有这些标题元素。再比如,你可能需要同时获取所有带有特定CSS类
product-name
div
元素,以及所有
id
featured-item
p
元素,那么
//div[@class='product-name'] | //p[@id='featured-item']
就能轻松搞定。

在我看来,这个运算符的强大之处在于它极大地提高了XPath表达式的灵活性和表达力。它让我们可以跨越结构差异,将逻辑上相关但物理位置分散的数据点聚合起来,为后续的数据处理打下基础。它不是在筛选,而是在“收集”——收集所有符合任一条件的节点。

XPath的
|
运算符与AND/OR逻辑操作符有什么区别

这是个特别好的问题,我个人在初学XPath时也曾有过类似的疑惑。

|
运算符和
and
/
or
逻辑操作符虽然都包含“或”的语义,但它们的应用场景和操作对象是截然不同的。

简单讲,

|
运算符是节点集联合操作符。它作用于两个或多个完整的XPath路径表达式,将这些表达式各自返回的节点集进行合并。你可以把它想象成集合论里的“并集”操作。它处理的是“A路径找到的节点”和“B路径找到的节点”的合并。例如,
//a | //p
会找到所有的
标签和所有的

标签,然后把它们放在一个结果集里。

and
or
布尔逻辑操作符。它们通常用在XPath的谓语(p
redicates)中,也就是方括号
[]
里,用来构建条件判断。它们操作的是条件表达式的真假值,最终返回一个布尔结果(True或False),从而决定是否选择当前正在被评估的节点。它们处理的是“当前节点是否同时满足条件A和条件B”或者“当前节点是否满足条件A或条件B”。

比如,

//div[contains(@class, 'product') and @id='featured']
这个表达式,它会寻找所有
div
元素,但只有当这个
div
class
属性包含
product
并且它的
id
属性是
featured
时,这个
div
才会被选中。这里
and
连接的是两个条件。

再看

//a[starts-with(@href, '/blog') or contains(@href, 'archive')]
,它会选择所有
标签,只要它的
href
属性以
/blog
开头或者包含
archive
字符串。这里
or
连接的也是两个条件。

所以,核心区别在于:

|
合并的是结果集,而
and
/
or
是用来筛选单个节点是否符合特定条件。理解这一点,对于编写精确且高效的XPath表达式至关重要。

在实际抓取数据时,
|
运算符有哪些高级应用场景?

|
运算符在真实世界的数据抓取中,其应用远比表面上看起来要灵活和强大。我个人在处理那些结构不一致或动态变化的网页时,特别依赖它。

uBrand
uBrand

一站式AI品牌创建平台,在线品牌设计,AI品牌策划,智能品牌营销;uBrand帮助创业者轻松打造个性品牌!

下载

一个很常见的场景是处理页面结构的不确定性。比如,一个新闻网站的标题,有时可能在

标签里,但如果它是专题页面的子标题,又可能出现在

里,甚至某些老旧页面会用

。如果你想统一抓取所有文章标题,无论其具体标签,那么
//h1[@class='article-title'] | //h2[@class='article-title'] | //h3[@class='article-title']
就能一网打尽。这避免了你需要写多条规则,然后手动合并结果。

再比如,合并来自不同父级元素下的相似数据。假设一个商品详情页,商品名称可能在一个

div
下的
h1
里,但旁边推荐商品的名称却在另一个
section
下的
h3
里。如果你希望把所有商品名称都抓出来,而不用关心它们具体是主商品还是推荐商品,
//div[@class='main-product']/h1/text() | //section[@class='related-products']//h3/text()
就能实现。它允许你跨越DOM树的不同分支来收集信息。

另一个我经常用到的场景是处理A/B测试或网站改版带来的元素路径变化。网站可能会测试两种不同的布局,导致同一个逻辑上的元素,在DOM树中的路径有所不同。或者,网站改版后,原来是

div[@id='content']
的元素,现在变成了
section[@class='main-content']
。为了保持抓取规则的健壮性,你可以这样写:
//div[@id='content'] | //section[@class='main-content']
。这样,无论网站是哪种结构,你的XPath都能找到目标。

甚至,在某些情况下,为了获取一个元素的特定属性或文本,但其位置不固定

|
也能派上用场。例如,你可能想抓取所有链接的
href
属性,以及所有图片链接的
src
属性。虽然这通常可以通过更复杂的单个XPath实现,但
//a/@href | //img/@src
这种直观的写法,能直接合并这些不同类型的属性值,方便后续统一处理。

总的来说,

|
运算符在那些需要“宽泛匹配”或“多路径收集”的场景下,展现出其独特的价值。它让数据抓取变得更加灵活,能够应对真实世界中网页结构的多变性。

使用
|
运算符时,可能遇到哪些常见问题或性能考量?

尽管

|
运算符功能强大,但在实际使用中,我们确实需要注意一些潜在的问题和性能考量。这就像任何工具一样,用得好能事半功倍,用得不好也可能带来麻烦。

首先是性能问题。当你的XPath表达式变得非常复杂,尤其是包含多个

//
(descendant-or-self axis)和多个
|
运算符时,性能可能会受到影响。
//
本身就是一种“全页扫描”操作,如果再用
|
去合并多个这样的扫描结果,解析器可能需要做更多的工作。每次
|
操作都会导致其左右两边的子表达式被独立评估,然后结果集再进行合并和去重。如果你的页面DOM结构非常庞大,或者你的XPath表达式过于宽泛,这可能会导致抓取时间显著增加。我的经验是,尽量让每个子表达式都尽可能精确,缩小搜索范围,而不是盲目地使用
//

其次,关于结果集的顺序。XPath 1.0规范并没有强制规定

|
操作后结果集的顺序。虽然大多数现代XPath解析器会尝试保持“文档顺序”(document order),即节点在HTML/XML文档中出现的顺序,但这不是一个严格的保证。如果你对结果集的顺序有严格要求,比如你希望先拿到
h1
再是
h2
,那么你可能需要在获取结果后,在你的编程语言层面进行额外的排序处理。这是个小细节,但有时候会让人困惑。

再来就是误用或滥用。有时,我们可能会不自觉地用

|
来解决一些本可以用更简洁、更高效的单个XPath表达式解决的问题。例如,如果你想选择所有
class
属性是
intro
summary
p
标签,
//p[@class='intro' or @class='summary']
通常比
//p[@class='intro'] | //p[@class='summary']
更推荐。虽然在这类简单场景下,两者结果可能相同,但前者是在一个
p
节点集内部进行条件筛选,而后者是先找出两组
p
节点再合并。在语义上,它们是不同的操作,前者是“筛选”,后者是“合并”。理解这种细微差别,有助于写出更语义化且可能更高效的XPath。

最后,调试复杂表达式也是一个挑战。当一个XPath表达式变得很长,包含多个

|
和复杂的谓语时,一旦出现问题,定位错误会比较困难。我的建议是,在编写复杂XPath时,分步测试每个子表达式,确保它们各自都能按预期工作,然后再逐步组合。这能大大提高调试效率。

总而言之,

|
运算符是XPath工具箱里一把非常锋利的刀,用得好能事半功倍,但也要注意其特性,避免引入不必要的性能开销或逻辑陷阱。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1503

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

233

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

87

2025.10.17

pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1903

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

2094

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

1086

2024.11.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

340

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

54

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

CSS教程
CSS教程

共754课时 | 25.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号