爬虫 - XPath

定义

XPath,全称 XML Path Language,即 XML 路径语言,它是一门在XML文档中查找信息的语言,是一个文档解析库。XPath 最初设计是用来搜寻XML文档的,但是它同样适用于 HTML 文档的搜索。
所以在做爬虫时,可以使用 XPath 来做相应的信息抽取,定位节点。XPath有特定的语法和函数去定位节点、获取节点信息

常用规则

表达式 描述
nodename 选取此节点的所有子节点
/ 从当前节点选取直接子节点
// 从当前节点选取子孙节点
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性

1. lxml的etree模块可以对HTML文档进行自动修正

直接解析文本

from lxml import etree
text = '''
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a>
     </ul>
 </div>
'''
html = etree.HTML(text)
result = etree.tostring(html)
print(result.decode('utf-8'))

读取文件,再解析

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = etree.tostring(html)
print(result.decode('utf-8'))

test.html

<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a>
     </ul>
 </div>

2. 选取所有节点

选取所有节点:XPath语法://*

from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//*')
print(result)

只选取所有li节点:XPath语法://li

from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li')
print(result)
print(result[0])

3. 获取孩子节点(/)和孙子节点(//)

孩子节点

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li/a')
print(result)

孙子节点

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//ul//a')
print(result)

这个例子中,运行结果是相同的。因为ul里面只有一个a。

4. 获取父节点

XPath语法:/..或者parent::

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//a[@href="link4.html"]/../@class')
print(result)
from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//a[@href="link4.html"]/parent::*/@class')
print(result)

5. 获取有相应属性的节点

选取 class 为 item-1 的 li 节点

from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-1"]')
print(result)

6. 获取节点的文本

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]/text()')
print(result)

# 运行结果:['\n     ']

匹配到的结果就是被修正的 li 节点内部的换行符,因为自动修正的li节点的尾标签换行了
即选中的是这两个节点:

<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</li>

其中一个节点因为自动修正,li 节点的尾标签添加的时候换行了,所以提取文本得到的唯一结果就是 li 节点的尾标签和 a 节点的尾标签之间的换行符

如果我们想获取 li 节点内部的文本就有两种方式,一种是选取到 a 节点再获取文本,另一种就是使用 //

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]/a/text()')
print(result)

# 运行结果:['first item', 'fifth item']
from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]//text()')
print(result)

# 运行结果:['first item', 'fifth item', '\n     ']

先选取到特定的子孙节点,然后再调用 text() 方法获取其内部文本,这样可以保证获取的结果是整洁的

猜你喜欢

转载自www.cnblogs.com/allen2333/p/9300122.html
今日推荐