简介

XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。

XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初XPath的提出的初衷是将其作为一个通用的、介于XPointer与XSL间的语法模型。但是XPath很快地被开发者采用来当作小型查询语言。

在我所熟悉的国内几种采集器(如八爪鱼、后羿采集器和火车采集器)中都广泛使用XPath作为其核心网页标记定准工具。

因此,掌握XPath的话,再使用各种采集器软件便是小菜一碟。但是,这并要求对于XPath有非常彻底的掌握,但是也需要用户有一定的HTML与CSS选择器等基础;否则,还是比较困难的,无论工具官方怎么解释,都绕不过这个“槛”去!

语法

选取节点 XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。

下面列出了最有用的路径表达式:

表达式

描述

nodename

选取此节点的所有子节点。

/

从根节点选取,即绝对路径表示方式。

//

从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置

.

选取当前节点。

..

选取当前节点的父节点。

@

选取属性。

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式

结果

bookstore

选取 bookstore 元素的所有子节点。

/bookstore

选取根元素 bookstore。

注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!

bookstore/book

选取属于 bookstore 的子元素的所有 book 元素。

//book

选取所有 book 子元素,而不管它们在文档中的位置。

bookstore//book

选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。

//@lang

选取名为 lang 的所有属性。

标准函数

本文不再赘述有关XPath的各种使用细节,具体的知识各位可参考文后引用资料。

XPath 含有超过 100 个内建的函数。这些函数用于字符串值、数值,日期和时间比较、节点和 QName 处理、序列处理、逻辑值等等。

本文侧重介绍7个常用的XPath函数及其在上述采集工具中的应用。

1.text函数

第一个是text函数,是通过文本来定位网页元素的函数,它查找的是当前元素的文本。写法是[text)="文本]。

XPath|掌握数据采集工具的核心技巧_八爪鱼

【注意】使用tex0=“文本"时,双引号内的文本必须和网页上的一模一样!

还有一个与text类似的函数是string函数。

text函数是通过文本来定位网页元素的函数,它查找的是当前元素的文本写法是[tex)="文本]。string函数则是用字符串来定位网页元素的函数,它查找的是当前元素及其包含的所有元素的文本。

【注意】string和text都要求双引号内文本和网页源码中的完全一样,稍有不同就会定位不到。为了实现更灵活的定位,一般都会配合 contains0函数来使用。

第二个是 contains0函数,是用来判断标签的文本中是否包含XX或者判断某个属性的属性值是否包含X×X写法是[ contains(text())文本或[ contains(@属性,属性值")。

2.contains函数

第二个是 contains函数,是用来判断标签的文本中是否包含XX或者判断某个属性的属性值是否包含X×X写法是[ contains(text())文本或[ contains(@属性,属性值")

例如,对于上面的表达,可以写成如下形式:

Xpath可以这样写:// a[contains(text(),"后页")或/ a[contains( string(),"后页")]

含义即:超链接的文本标签中包含“后页”即是满足条件的超链接(也称为“锚”)标签。

【注意】使用 contains函数,text和 string双引号里的文本不需要和网页中的一模一样,只需填写一部分就可以。这可以避免因网站改版,如网页中少了大于号或前后多了空格,而定位不到的情况。

3.position函数

第三个是 position函数,它是用来定位节点的位置和范围,常用于控制循环列表的项。写法是:

[position()=<>数字]

使用举例,如下图:

XPath|掌握数据采集工具的核心技巧_八爪鱼_02

注意到,我在调试面板的XPath表达式中输入了:

.//*[@id='managerBlogList']/div[position()<3]

然后,按下回车键。于是,我的草稿箱中的最顶部两个列表项即被以蓝色虚框线高亮显示。太漂亮了!

用上述方式,结合XPath教程,你可以用可视化方式迅速学习常用XPath了!


4.last函数

第四个是last函数,同 position函数功能类似,它的意思是定位最后一个标签,写法是:

[last()]

补充:根据这个函数的含义介绍,那么表达式

[last()-1]

的含义即是代表倒数第2项,而表达式

[last()-n]

 即代表倒数第n项了。

5.逻辑函数

第五是and/or/not函数,它们通常用来对标签所含的属性进行限定。写法是:

[@属性1 and @属性2]、[@属性1 or @属性2]、[not(@属性1)】

举例:

XPath|掌握数据采集工具的核心技巧_xml_03

6.following-sibling

第六个是following- sibling函数,它的意思是选取当前节点之后的所有同级节点,不包括它自己。写法是

[/following-sibling∷*]

其中,单斜杠是绝对路径。注意:“::"后面,如果你要定位a标签就写a,定位span标签就写span,如果想全部定位就写*,*代表可以是仼意标签。

另一个与此类似的函数是preceding- sibling函数。 preceding- sibling定位的是当前结点之前的所有同级结点,注意区分。

举例:

//a[text()="abc"]/preceding-sibling::a

含义是:如果【abc】代表一个链接类型的按钮,则上面表达式表达是定位(选择)到此标签前所有同级的链接类型按钮。

7.count

第七个是 count函数,用于判断是当前节点下某种子节点的个数是否大于小于或等于某个数值。写法是

[count(子节点标签)=<>数字]

举例:

//div[@id="entry"]/div[@class="block"][count(div[@class="clear"])=0]

含义是:id属性为“entry”的div标签下的所有class属性为“block”的div标签下所有那些class属性不是“clear”的div标签。

关于Firefox当前的XPath插件!

略令人遗憾的是,当前Firefox最新版本并不提供对XPath(官方版本)的内置支持。虽然有一些第三方XPath插件,但是功能也有限(例如Ruto评分最高),无法在用户自建XPath表达式的情况下以直观方式显示符合XPath表达条件的网页标签(可能是一个或者一组)。

因此,要充分使用XPath功能(可以在用户指定标记时自动生成XPath表达式,也可能在人工构造表达式时以高亮方式圈出符合条件的一个或者一组网页标记),还需要用户安装早期版本的Firefox及对应插件。

本人建议使用八爪鱼官方提供的版本及插件即可:

__________________________________________________________________

54版本火狐浏览器的下载地址

64位:​​http://ftp.mozilla.org/pub/firefox/releases/54.0.1/win64/zh-CN/ ​

32位:​​http://ftp.mozilla.org/pub/firefox/releases/54.0.1/win32/zh-CN/​

火狐FirePath插件

压缩包下载地址:​​https://pan.baidu.com/s/1rushghRy2uGs99-XFyxDNg​​​,提取码:fkb4

__________________________________________________________________

本文不推荐使用Google浏览器插件的原因大家相信都知道,在此不赘述。

在京东客户评价数据抓取中的应用

在我的上一篇文章​​数据采集器实战|八爪鱼评价数据采集​​中,有至少两处需要需要用户手动修改XPath表达式。

【1】为了精准采集到所有差评,需修改【循环列表】XPath

进入【循环列表】设置页面,修改XPath为  //div[@id='comment-6']/div[position()<11],并保存。

【2】默认的【循环翻页】XPath 无法精准定位到差评的翻页,需修改【循环翻页】XPath

进入【循环翻页】设置页面,修改XPath为://div[@id='comment-6']//div[@class="ui-page"]//a[@class="ui-pager-next"] ,然后保存。

相信结合前面的函数介绍,这里的两个例子不需要作过多说明了。但是,还有一点需要强调:

//的含义是相对路径,/的含义是绝对路径

在XPath表达式中,//div[@id='comment-6']/div[position()<11]示例中/的含义是指定位到id属性为“comment-6"的div标签后,其下直属子标签div满足指定条件。

//div[@id='comment-6']//div[@class="ui-page"]//a[@class="ui-pager-next"]示例中第二个和第三个//表示对应的标签并不一定是前面标签下的直属标签!!!这一点一定要弄准确!


引用