当前位置 : 主页 > 编程语言 > python >

利用python爬虫(part6)--用Xpath匹配带来的数据合并问题

来源:互联网 收集:自由互联 发布时间:2022-06-15
学习笔记 如果在本Blog里看到拼音,那可能是由于​​​第一次shen he没通过​​被逼的,葛优躺,不知所措。 用Xpath匹配带来的数据合并问题 在我以往的爬虫案例中(比如:X凰X闻案例),

学习笔记
如果在本Blog里看到拼音,那可能是由于​​​第一次shen he没通过​​被逼的,葛优躺,不知所措。


用Xpath匹配带来的数据合并问题

在我以往的爬虫案例中(比如:X凰X闻案例),我用Xpath分别得到了Xin闻名称列表name_list和Xin闻详情链接列表link_list,并用zip()函数,形成一个生成器对象,将两个列表’合在一起’。

部分代码如下(html源代码就不贴在这里了,太占位置了):

parse_html = etree.HTML(html)
link_xpath = \
'//ul[@class="news-stream-basic-news-list"]/li[@class="news-stream-newsStream-news-item-has-image clearfix news_item"]//h2/a/@href'
name_xpath = \
'//ul[@class="news-stream-basic-news-list"]/li[@class="news-stream-newsStream-news-item-has-image clearfix news_item"]//h2/a/text()'

link_list = parse_html.xpath(link_xpath)
link_list = ['http:{}'.format(i) for i in link_list]
name_list = parse_html.xpath(name_xpath)
#只要使用xpath方法进行数据爬取,结果就会返回一个列表
data_zip = zip(name_list, link_list)
for item in data_zip:
print(item)

这种方法看起来很方便,但是利用内置生成器函数zip(),会产生一些严重的问题,进而导致后续的数据分析错误。

  • 举个例子

有如下HTML代码:

<ol>
<li class="Ra01">
<name class = 'Bunny01'>小黄</name>
<age>8</age>
<food>胡萝卜</food>
</li>
<li class="Ra01">
<name class = 'Bunny02'>大白</name>
<age></age>
<food>白菜</food>
</li>
<li class="Ra02">
<name class = 'Bunny03'>奥尼尔</name>
<age>20</age>
<food>提草</food>
</li>
<li class="Ra03">
<name class = 'Bunny03'>王子</name>
<age>30</age>
<food>进口提草</food>
</li>

</ol>

可以看到这个HTML页面中有4对name和age数据,但是由于某些不明原因,导致某些age节点中的数据丢失。

如果此时,我们要获取HTML页面中name节点和age节点中的文本中,则它们的Xpath可以写成:

#name节点内文本
//ol/li/name/text()
#age节点内文本
//ol/li/age/text()

此时我们编写python代码:

# -*- coding: utf-8 -*-

from lxml import etree

html = \
"""
<ol>
<li class="Ra01">
<name class = 'Bunny01'>小黄</name>
<age>8</age>
<food>胡萝卜</food>
</li>
<li class="Ra01">
<name class = 'Bunny02'>大白</name>
<age></age>
<food>白菜</food>
</li>
<li class="Ra02">
<name class = 'Bunny03'>奥尼尔</name>
<age>20</age>
<food>提草</food>
</li>
<li class="Ra03">
<name class = 'Bunny03'>王子</name>
<age>30</age>
<food>进口提草</food>
</li>

</ol>
"""

parse_html = etree.HTML(html)

#获取所有name节点内文本
name_list = parse_html.xpath('//ol/li/name/text()')
print(name_list)
print('-'*20)

#获取所有age节点内文本
age_list = parse_html.xpath('//ol/li/age/text()')
print(age_list)

控制台输出:

['小黄', '大白', '奥尼尔', '王子']
--------------------
['8', '20', '30']

我们看到,由于HTML源代码中某些age节点内的数据丢失,导致name_list和age_list的长度不一致,所以此时如果我们用内置生成器zip(),不仅会导致数据丢失,而且会导致name和age不匹配,这么说可能不够形象,我们zip()一下,试试:

for item in zip(name_list, age_list):
print(item)

控制台输出:

('小黄', '8')
('大白', '20')
('奥尼尔', '30')

我们看到,结果只输出了3条数据,且从’大白开始,各个name和age不匹配。

根据HTML源代码,我们得到的数据应该是这样的:

('小黄', '8')
('大白', '')
('奥尼尔', '20')
('王子', '30')

所以,我们要换一种思维,用另一种方法,将数据’拼接’在一起。

比如:先获取每一个li节点对象,将这些对象装在一个列表中,再遍历这个列表中的li节点对象,并分别对各个li节点对象获取name和age文本数据,并将它们拼接在一起。同样,我们用代码演示一遍:

parse_html = etree.HTML(html)

#获取所有li节点(大节点)对象
li_list = parse_html.xpath('//ol/li')
#print(name_list)
#print('-'*20)

data_list = []
#遍历li节点对象列表
for item in li_list:

name = item.xpath('./name/text()')
age = item.xpath('./age/text()')
if not name:
name = 'None'
if not age:
age = '0'
data_list.append((name[0], age[0]))

for item in data_list:
print(item)

注意,我们看到上面Xpath代码​​./name/text()​​​中,最开头有一个​​.​​点,这个点有当前路径的意思,换句话说,这个点代表了li节点所在的位置。

控制台输出:

('小黄', '8')
('大白', '0')
('奥尼尔', '20')
('王子', '30')

可喜可贺!得到的name和age数据一个不少,且没有出现name和age匹配错误的现象。

上一篇:利用python爬虫(part10)--Xpath节点集与函数
下一篇:没有了
网友评论