01 引言
上一期主要介绍了XPath
的基本语法,以及常用的技巧,用于快速入门。但是使用的技巧中引入了轴(Axes)以及函数的概念,为了能够更加游刃有余的使用进阶技巧,我们完整的介绍一下XPath
的高阶玩法。
02 轴(Axes)
在 XPath
中,轴(Axes)是用来定位 XML 或 HTML 文档中节点与当前节点之间关系的关键概念,它是是 XPath 中用于定义方向和节点关系的一种机制。通过轴,您可以向上、向下、向左或向右查找节点。每个轴表示一个特定的方向,并能返回相对于当前节点的不同节点集合。
XPath
提供了多种轴,用于定位当前节点的父节点、子节点、兄弟节点、祖先节点等。
2.1 轴的枚举
轴名称 | 含义 |
---|---|
ancestor | 直译:祖先。选取当前节点的所有先辈(父、祖父等)。 |
ancestor-or-self | 直接:祖先或自己。选取当前节点的所有先辈(父、祖父等)以及当前节点本身。 |
attribute | 直译:属性。选取当前节点的所有属性。 |
child | 直译:孩子。选取当前节点的所有子元素(不包含孙)。 |
descendant | 直译:后代。选取当前节点的所有后代元素(子、孙等)。 |
descendant-or-self | 直译:后代或自己。选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 |
following | 直译:后面。选取文档中当前节点的结束标签之后的所有节点(包括子节点)。 |
following-sibling | 直译:后面的兄弟节点。选取当前节点之后的所有兄弟节点(不包括子节点) |
namespace | 直译:名称空间。选取当前节点的所有命名空间节点。 |
parent | 直译:父亲。选取当前节点的父节点(最近的一个)。 |
preceding | 直译:前一个。选取文档中当前节点的开始标签之前的所有节点。 |
preceding-sibling | 直译:前一个兄弟节点。选取当前节点之前的所有同级节点。 |
self | 直译:自身。选取当前节点。 |
用法:轴名称::节点名称
基础的语法只能按照层级一级一级的获取。而轴则可以帮助我们实现节点之间的跨越。
2.2 实战案例
实战之前我们定义一个Html页面:
<html>
<body>
<div class="content">
<h1>XPath轴和函数详细语法</h1>
<div class="detail">
<span>掌握XPath轴,实现爬虫效率翻倍</span>
<ul>
<li>节点1</li>
<li>节点2</li>
<li style="color:blue">我在这里。节点3</li>
<li>节点4</li>
<li>节点5</li>
</ul>
</div>
<div class="following">
<span>掌握函数语法,快速定位标签</span>
<div>常用函数</div>
</div>
<div>
</body>
</html>
ancestor
和ancestor-or-self
的使用
简单来说就是,一层和多层的关系。
# <li style="color:blue">我在这里。节点3</li> 节点的祖先们
//li[@style]/ancestor::*
# <li style="color:blue">我在这里。节点3</li> 节点的祖先们和自己
//li[@style]/ancestor-or-self::*
浏览器执行结果:
如图所示:ancestor
获取到了所有的祖先节点
attribute
、namespace
、parent
、self
# <li style="color:blue"></li> 节点的sytle属性
# 获取所有属性使用通配符*
//li[@style]/attribute::style
# HTML本身不使用命名空间,名称空间主要用于xml,这里在赘述。
# <li style="color:blue"></li> 节点父级节点
# 只能取一层
//li[@style]/parent::*
# <li style="color:blue"></li> 节点自身
# 同 //li[@style]一致
//li[@style]/self::*
浏览器执行结果:
child
、descendant
和descendant-or-self
# <div class="detail"></div> 的子节点
//div[@class='detail']/child::*
# <div class="detail"></div> 的后代们
//div[@class='detail']/descendant::*
# <div class="detail"></div> 的后代们和自己
//div[@class='detail']/descendant-or-self::*
浏览器执行结果:
following
和following-sibling
#<h1>XPath轴和函数详细语法</h1> 的后面的所有div节点
//div[1]/h1/following::div
#<h1>XPath轴和函数详细语法</h1> 的后面的所有div兄弟节点
//div[1]/h1/following-sibling::div
浏览器执行结果:
preceding
和preceding-sibling
# <div class="following"></div>的前面的所有节点
//div[@class='following']/preceding::*
# <div class="following"></div>的前面的所有兄弟节点
//div[@class='following']/preceding-sibling::*
浏览器执行结果:
03 函数
XPath
提供了丰富的内置函数,可以处理字符串、位置索引以及逻辑运算等复杂场景。
3.1 字符串函数
starts-with()
、contains()
和text()
# starts-with() 表示属性以XX开始
//div[starts-with(@class, 'follow')]
# contains() 表示属性包含XX
//div[contains(@class, 'tail')]
# text() 表示文本值
//div[text()=='常用函数']
浏览器执行结果:
3.2 位置索引
last()
和position()
# 获取<ul>里面的最后一个li元素
# 如果获取的是单一元素,可以通过string()的方式查看文本元素
//ul/li[last()]
# 获取<ul>里面的倒数第二个li元素
# 如果获取的是单一元素,可以通过string()的方式查看文本元素
//ul/li[last()-1]
# 获取<ul>里面的位置小于3的li元素
//ul/li[position() < 3]
浏览器执行结果:
3.3 逻辑运算
and
、or
和not
# AND 关系:class等于content,并且第一个
//div[@class='content' and position() = 1]
# OR 关系:class等于content或者class等于detail
//div[@class='content' or @class='detail']
# OR 关系:div不包含class
//div[not(@class)]
浏览器执行结果:
04 小结
了解了本文,可以深入了解XPath
的高阶用法。收藏本文,下次遇到复杂页面解析时,这些高阶技巧将助你轻松突破抓取瓶颈!你在实际工作中遇到过哪些XPath难题?欢迎留言讨论!