Python公开课 - 页面解析之XPath

前言

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

XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。

XPath最初是用来搜寻XML文档的,但是它同样适用于HTML文档的搜索。所以在做爬虫时,可以使用 XPath 来做相应的页面解析。

XPath常用规则

  • nodename - 选取此节点的所有子节点
  • / - 从当前节点选取直接子节点
  • // - 从当前节点选取子孙节点
  • . - 选取当前节点
  • .. - 选取当前节点的父节点
  • @ 选取属性

举个简单的例子进行说明:

//p[@lang=’english') 

这就是一个 XPath 规则,它代表选择所有名称为p,且属性lang 的值为english的节点。

XPath节点

在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。

from lxml import etree
import lxml.html
text = '''
  <html>
  <body>
    <div>
      <ul>
        <li class="item-0">
          <a href="linkl.html">0 item</a>
        </li>
        <li class="item-1">
          <a href="link2.html">2 item</a>
        </li>
        <li class="item-inactive item-1">
          <a href="link3.html">3 item</a>
        </li>
        <li class="item-2">
          <a href="link4.html">4 item</a>
        </li>
        <li class="item-3">
          <a href="links5.html">5 item</a>
        </li>
      </ul>
    </div>
  </body>
  </html>'''
html = lxml.html.fromstring(text)
result= etree.tostring(html)
print(result.decode('utf8'))

父节点 - Parent

在上面的例子中,ul节点是所有li的父节点,li是a的父节点

子节点 - Children

同理li是ul的子节点,a是li的子节点

同胞 - Sibling

所有的ul节点下的li节点都是同胞

先辈 - Ancestor

a的先辈包括li, ul, div等

子孙 - Descendant

所有节点都是html节点的子孙

查找

按属性查找

我们还可以用@符号进行属性过滤,比如如果要选取class为item-0 的li节点,可以这样实现:

result = html.xpath('//li[@class="item-0"]')
print(result)

输出:
[<Element li at 0x7f8431bc5548>]

包含关系属性查找

通过 contains()方法,第一个参数传人属性名称,第二个参数传人属性值,只要此属性包含所传入的属性值,就可以完成匹配了:

result = html.xpath('//li[contains(@class,"item-inactive")]/a/text()')
print(result)

输出:
['3 item']

多属性精确查找

and 其实是 XPath 中的运算符号,通过它可以实现多条件匹配:

result = html.xpath('//li[contains(@class,"item-inactive") and contains(@class,"item-1")]/a/text()')
print(result)

输出:
['3 item']

按顺序查找

这里我们使用了last()函数来选择最后一个,我们也可以有更多函数可以进行操作,参见XPath常用函数总结

result = html.xpath('//li[last()]/a/text()')
print(result)

输出:
['5 item']

节点轴查找

我们调用了 ancestor 轴,可以获取所有祖先节点。 其后需要跟两个冒号,然后是 节点的选择器,这里我们直接使用*,表示匹配所有节点,

result = html.xpath('//li[1]/ancestor::*')
print(result)

输出:
[<Element html at 0x7f48976dcef8>, <Element body at 0x7f48976f2548>, <Element div at 0x7f4897682c78>, <Element ul at 0x7f4897682d68>]

数据抽取

文本获取

用 XPath 中的 text()函数获取节点中的文本:

result = html.xpath('//li[@class="item-3"]/a/text()')
print(result)

输出:
['5 item']

属性获取

用@符号来获取属性值:

result = html.xpath('//li/a/@href')
print(result)

输出:
['linkl.html', 'link2.html', 'link3.html', 'link4.html', 'links5.html']

小结

本章基本上把可能用到的 XPath 选择器介绍完了。 XPath 功能非常强大,内置函数非常多, 熟练使用之后,可以非常方便的对页面进行内容提取。

相关阅读