网页内容抓取工具(XPath的节点(Node)中的核心就是节点及其关系)

优采云 发布时间: 2021-10-14 23:17

  网页内容抓取工具(XPath的节点(Node)中的核心就是节点及其关系)

  上一节我们详细介绍了lxml.html的各种操作。接下来,如果我们熟练掌握XPath,就可以熟练地提取网页内容。

  什么是 XPath?

  XPath 的全称是 XML Path Language,它是一种用于在 XML (HTML) 文档中查找信息的语言。它有4个特点:

  

  我们从网页中提取数据,主要应用前两点。

  XPath 路径表达式

  使用XPath,我们可以很方便的定位网页中的节点,也就是找到我们关心的数据。这些路径与计算机目录和URL的路径非常相似,路径的深度用/表示。

  XPath注解函数库

  标头中内置了 100 多个函数。当然,我们对数据提取的使用是有限的,因此没有必要记住所有 100 多个函数。

  Xpath节点(Node)

  XPath 的核心是 Node,它定义了 7 种不同类型的节点:Element、Attribute、Text、Namespace、Processing-instruction、Comment(注释)和 Document 节点

  这些节点形成一个节点树,树的根节点称为文档节点。

  注释是html中的注释:``

  命名空间、处理指令和网页数据提取基本无关,这里不再赘述。

  下面我们以一个简单的html文档为例来说明不同的节点及其关系。

  

      ABC              home         python       

  这个 html 中的节点是:

  XPath 节点之间的关系

  节点之间的关系完全复制了人类继承的世代关系,但只是直接关系,并没有叔叔叔叔等旁系关系。

  我们以上面的html文档为例来说明节点关系:

  家长

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

  比如body的父节点是html,body是div和ul的父节点。

  孩子们

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

  例如,body 有两个孩子:div 和 ul,ul 也有两个孩子:两个 li。

  兄弟

  同一代具有相同的父节点。

  例如,div 和 ul 是同一代。

  祖先

  节点的父节点及其上方的节点。

  比如li的父母是:ul, div, body, html

  后裔

  节点的子节点及其后代。

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

  XPath 节点的选择

  节点的选择是通过路径表达来实现的。这是我们从网络中提取数据时的关键,我们需要精通它。

  下表是更有用的路径表达式:

  表情说明

  节点名

  选择当前节点的所有名为 nodename 的子节点。

  /

  从根节点选择,当在路径中间时,表示一级路径

  //

  从当前节点中选择文档中的节点,可以是多级路径

  .

  从当前节点中选择

  ..

  从父节点中选择

  @

  按属性选择

  接下来我们通过具体的例子来加深对路径表达式的理解:

  路径表达式说明

  /html/body/ul/li

  按照路径选择从根节点开始的 li 元素。返回多个。

  //ul/li[1]

  li 元素仍然被选中,但路径在多个阶段跳转到 ul/li。[1] 表示只取第一个 li。

  //li[last()]

  还是选择了li,只是路径比较曲折。[last()] 表示取最后一个 li 元素。

  //li[@class]

  选择名称为 li 且具有 class 属性的根节点的所有后代。

  //li[@class="item"]

  选择名称为li、class属性为item的根节点的所有后代。

  //正文/*/li

  选择名为 li 的 body 的孙节点。* 是通配符,表示任意节点。

  //li[@*]

  选择所有具有属性的 li 元素。

  //身体/div `

  `//身体/ul

  选择 body 的所有 div 和 ul 元素。

  正文/div

  相对路径,选择当前节点的body元素的子元素div。绝对路径以 / 开头。

  XPath 函数

  Xpath 的功能很多,涉及到错误、值、字符串、时间等,但是我们在从网页中提取数据的时候只用到了一小部分。其中最重要的是与字符串相关的函数,例如 contains() 函数。

  收录(a, b)

  如果字符串 a 收录字符串 b,则返回 true,否则返回 false。

  例如:contains('猿人学习Python','Python'),返回true

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

  

     ... 

  此 html 中的 div 具有三个类值。第一个貌似是贴文,后两个是格式的更多设置。如果我们想提取网页中所有已发布的消息,只需要匹配post-item,那么我们可以使用contains:

  

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

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

  但是在lxml的xpath中使用ends-with(),matches()会报错

  

In [232]: doc.xpath('//ul[ends-with(@id, "u")]') --------------------------------------------------------------------------- XPathEvalError                            Traceback (most recent call last)  in () ----> 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 以符合标准的方式通过 libxml2 和 libxslt 支持 XPath 1.0、XSLT 1.0 和 EXSLT 扩展。

  然后我在维基百科上找到了 Xpath 2.0 和 1.0 之间的区别。果然,ends-with(),matches()只属于2.0。下图中,粗体部分收录在1.0中,其他部分也收录在2.0中:

  

  XPath 2.0 和 1.0 的区别

  好了,Xpath 提取网页内容的部分就完成了。

  来自“ITPUB博客”,链接:,如需转载请注明出处,否则将追究法律责任。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线