XPath 是什么?

XPath的全称是 XML Path Language,即XML 路径措辞,是一种在XML(HTML)文档中查找信息的措辞。
它有4点特性:

XPath 利用路径表达式在 XML 文档中进行导航XPath 包含一个标准函数库XPath 是 XSLT 中的紧张元素XPath 是一个 W3C 标准

我们从网页中提取数据,紧张运用前两点。

XPath 路径表达式

phpxpath抓取内容Python 爬虫网页内容提取最主要的对象xpath 一 Docker

利用XPath我们可以很随意马虎定位到网页中的节点,也便是找到我们关心的数据。
这些路径跟电脑目录、网址的路径很相似,通过/来表示路径的深度。

XPath 标注函数库

头内建了100多个函数,当然我们提取数据用到的有限,也就不用记住全部100多个函数了。

Xpath 的节点(Node)

XPath中的核心便是节点(Node),定义了7种不同类型的节点: 元素(Element)、属性(Attribute)、文本(Text)、命名空间(Namespace)、处理指令(processing-instruction)、注释(Comment)和文档节点(Document nodes)

这些节点组成一棵节点树,树的根节点被称为文档节点。

个中注释便是html里面的注释:<!-- 注释内容 -->

而命名空间、处理指令和网页数据提取基本没紧要,这里就不再详述。

下面我们以一个大略的html文档为例,来阐明不同的节点及其关系。

<html lang=\"大众en-US\"大众><body> <div>ABC</div> <ul id=\"大众menu\公众> <li class=\"大众item\"大众>home</li> <li class=\"大众item\公众>python</li> </ul></body></html>

这段html中的节点有:

文档节点: <html>元素节点:<li class=\公众item\公众>python</li>属性节点: id=\"大众menu\公众

XPath 节点的关系

节点间的关系完备照搬人类传宗接代的辈分关系,但只是嫡系关系,没有叔叔、大伯之类的旁系关系。

还是以上面的html文档为例来解释节点关系:

父(Parent)

每个元素节点(Element)及其属性都有一个父节点。

比如,body的父是html,而body是div、ul 的父亲。

子(Children)

每个元素节点可以有零个、一个或多个子。

比如,body有两个子:div,ul,而ul也有两个子:两个li。

同辈(Sibling)

同辈有相同的父辈节点。

比如,div和ul是同辈。

先辈(Ancestor)

某节点的父辈及其以上辈分的节点。

比如,li的父辈有:ul、div、body、html

后代(Descendant)

某节点的子及其子孙节点。

比如,body的后代有:div、ul、li。

XPath节点的选取

选取节点,也便是通过路径表达来实现。
这是我们在网页提取数据时的关键,要闇练节制。

下表是比较有用的路径表达式:

接下来通过详细的示例来加深对路径表达的理解:

XPath函数

Xpath的函数很多,涉及到缺点、数值、字符串、韶光等等,然而我们从网页中提取数据的时候只会用到很少的一部分。
个中最主要的便是字符串干系的函数,比如contains()函数。

contains(a, b)

如果字符串a包含字符串b,则返回true,否则返回false。

比如: contains(‘猿人学Python’, ‘Python’),返回true

那么它用在什么时候呢?我们知道,一个html标签的class是可以有多个属性值的,比如:

<div class=\"大众post-item text-red text-center\"大众> ...</div>

这段html中div有三个class值,第一个表面它是一条发布的,后面两个是对格式做了更多的设置。
如果我们想提取网页中所有发布的,只须要匹配到post-item 即可,这时候就可以用上contains了:

doc.xpath('//div[contains(@class, \"大众post-item\"大众)]')

跟contains()类似的字符串匹配的函数还有:

starts-with(string1, string2) 判断string1是否以string2开头ends-with(string1, string2) 判断string1是否以string2结尾matches(string, pattern) 通过正则表达式匹配

然而,在lxml的xpath中利用ends-with(), matches() 会报错

In [232]: doc.xpath('//ul[ends-with(@id, \公众u\"大众)]')---------------------------------------------------------------------------XPathEvalError Traceback (most recent call last)<ipython-input-232-79a4afc46a75> in <module>()----> 1 doc.xpath('//ul[ends-with(@id, \"大众u\"大众)]')src/lxml/etree.pyx in lxml.etree._Element.xpath()src/lxml/xpath.pxi in lxml.etree.XPathElementEvaluator.__call__()src/lxml/xpath.pxi in lxml.etree._XPathEvaluatorBase._handle_result()XPathEvalError: Unregistered function

lxml 竟然不支持ends-with(), matches()函数

到lxml官方网站去看看,原来它说了只支持 XPath 1.0:

lxml supports XPath 1.0, XSLT 1.0 and the EXSLT extensions through libxml2 and libxslt in a standards compliant way.

接着又在Wikipedia上找到Xpath 2.0 和 1.0 的差异比拟,果真ends-with(), matches() 只属于2.0。
下图中,粗体部分是1.0包含的,其它是2.0也有的:

好了,Xpath在网页内容提取中要用到的部分我们已经学完了。
下一节,我们将以实例讲解xpath详细提取数据的过程。