爬虫之XPath中级篇

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengqiuming/article/details/86373220

一 子节点

1 点睛

我们通过/或//即可查找元素的子节点或子孙节点。

2 实战1——获取子节点

2.1 代码

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
# 选择li节点的所有直接a子节点
# 这里通过追加/a即选择了所有li节点的所有直接a子节点。
# 因为//li用于选中所有li节点,/a用于选中li节点的所有直接子节点a,二者组合在一起即获取所有li节点的所有直接a子节点。
result = html.xpath('//li/a')
print(result)

2.2 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/4_1.py
[<Element a at 0x2138f113408>, <Element a at 0x2138f113448>, <Element a at 0x2138f113488>, <Element a at 0x2138f1134c8>, <Element a at 0x2138f113508>]

3 实战2——获取子孙节点

3.1 代码

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
# 要获取ul节点下的所有子孙a节点
result = html.xpath('//ul//a')
print(result)

3.2 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/4_1.py
[<Element a at 0x2ad495c3408>, <Element a at 0x2ad495c3448>, <Element a at 0x2ad495c3488>, <Element a at 0x2ad495c34c8>, <Element a at 0x2ad495c3508>]

3.3 说明

这里我们要注意/和//的区别,其中/用于获取直接子节点,//用于获取子孙节点。

二 父节点

1 实战1

1.1 代码

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
# 现在首先选中href属性为link4.html的a节点,然后再通过..获取其父节点,
# 然后再获取其class属性,相关代码如下:
result = html.xpath('//a[@href="link4.html"]/../@class')
print(result)

1.2 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/4_1.py
['item-1']

1.3 说明

检查一下结果发现,这正是我们获取的目标li节点的class。

2 实战2

2.1 代码

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
# 通过parent::来获取父节点
result = html.xpath('//a[@href="link4.html"]/parent::*/@class')
print(result)

2.2 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/4_1.py
['item-1']

三 属性匹配

1 代码

from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
# @符号进行属性过滤
# 选取class为item-1的li节点
# 这里我们通过加入[@class="item-0"],限制了节点的class属性为item-0,
# 而HTML文本中符合条件的li节点有两个,所以结果应该返回两个匹配到的元素。
result = html.xpath('//li[@class="item-0"]')
print(result)

2 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/4_1.py
[<Element li at 0x1e9db193408>, <Element li at 0x1e9db193448>]

3 说明

匹配结果正是两个。

四 文本获取

1 实战

1.1 文件

<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a>OK</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>

1.2 代码

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
# 这里获取的是li的文本,而不是a的文本
result = html.xpath('//li[@class="item-0"]/text()')
print(result)

1.3 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/4_1.py
['OK', '\r\n     ']

1.4 说明

OK对应的是第1个li的文本。

\r\n     对应的是第5个li的文本,因为parse会补齐li的尾标签,但尾标签会换行。

2 实战2——获取li中a标签的文本

2.1 点睛

是先选取a节点再获取a节点的文本

2.2 代码

from lxml import etree

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

2.3 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/4_1.py
['first item', 'fifth item']

2.4 说明

内容都是属性为item-0的li节点的文本。

3 实战3

3.1 点睛

使用//

3.2 代码

from lxml import etree

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

3.3 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/4_1.py
['first item', 'OK', 'fifth item', '\r\n     ']

3.4 说明

这里的返回结果是4个。可想而知,这里是选取所有子孙节点的文本,其中两个就是li的子节点a节点内部的文本,另外2个就是两个li节点内部的文本,即OK和换行符。

所以说,如果要想获取子孙节点内部的所有文本,可以直接用//加text()的方式,这样可以保证获取到最全面的文本信息,但是可能会夹杂一些换行符等特殊字符。如果想获取某些特定子孙节点下的所有文本,可以先选取到特定的子孙节点,然后再调用text()方法获取其内部文本,这样可以保证获取的结果是整洁的。

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/86373220