24.Python lxml解析库实战应用

本节通过编写一个简单的爬虫程序,进一步熟悉 lxml 解析库的使用。

确定信息元素结构

首先明确要抓取信息的网页元素结构,比如电影名称、主演演员、上映时间。通过简单分析可以得知,每一部影片的信息都包含在<dd>标签中,而每一<dd>标签又包含在<dl>标签中,因此对于dd标签而言,dl标签是一个更大的节点,也就是它的父辈节点,如下所示:

分析元素结构
图1:分析元素结构
 

当一个<dd>标签内的影片信息提取完成时,您需要使用同样的 Xpath 表达式提取下一影片信息,直到所有影片信息提取完成,这种方法显然很繁琐。那么有没有更好的方法呢?

基准表达式

因为每一个节点对象都使用相同 Xpath 表达式去匹配信息,所以很容易想到 for 循环。我们将 10 个<dd>节点放入一个列表中,然后使用 for 循环的方式去遍历每一个节点对象,这样就大大提高了编码的效率。

通过<dd>节点的父节点<dl>可以同时匹配 10 个<dd>节点,并将这些节点对象放入列表中。我们把匹配 10个<dd>节点的 Xpath 表达式称为“基准表达式”。如下所示:

xpath_bds='//dl[@class="board-wrapper"]/dd'

下面通过基准表达式匹配 <dd> 节点对象,代码如下:

  1. # 匹配10个dd节点对象
  2. xpath_bds='//dl[@class="board-wrapper"]/dd'
  3. dd_list=parse_html.xpath(xpath_bds)

输出结果:

[<Element dd at 0x36c7f80>, <Element dd at 0x36c7d50>, <Element dd at 0x36c7940>, <Element dd at 0x36c7d28>, <Element dd at 0x36c7bc0>, <Element dd at 0x36c7f58>, <Element dd at 0x36c7f30>, <Element dd at 0x36cc468>, <Element dd at 0x36cc170>, <Element dd at 0x37382b0>]

提取数据表达式

因为我们想要抓取的信息都包含在<dd>节点中,接下来开始分析<dd>节点包含的 HTML 代码,下面随意选取的一段<dd>节点包含的影片信息,如下所示:

  1. <dd>
  2. <i class="board-index board-index-4">4</i>
  3. <a href="/films/1292" title="海上钢琴师" class="image-link" data-act="boarditem-click" data-val="{movieId:1292}">
  4. <img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default">
  5. <img alt="海上钢琴师" class="board-img" src="https://p0.meituan.net/movie/609e45bd40346eb8b927381be8fb27a61760914.jpg@160w_220h_1e_1c">
  6. </a>
  7. <div class="board-item-main">
  8. <div class="board-item-content">
  9. <div class="movie-item-info">
  10. <p class="name"><a href="/films/1292" title="海上钢琴师" data-act="boarditem-click" data-val="{movieId:1292}">海上钢琴师</a></p>
  11. <p class="star">
  12. 主演:蒂姆·罗斯,比尔·努恩,克兰伦斯·威廉姆斯三世
  13. </p>
  14. <p class="releasetime">上映时间:2019-11-15</p> </div>
  15. <div class="movie-item-number score-num">
  16. <p class="score"><i class="integer">9.</i><i class="fraction">3</i></p>
  17. </div>
  18.  
  19. </div>
  20. </div>
  21. </dd>

分析上述代码段,写出待抓取信息的 Xpath 表达式,如下所示:

提取电影名信息:xpath('.//p[@class="name"]/a/text()')
提取主演信息:xpath('.//p[@class="star"]/text()')
提取上映时间信息:xpath('.//p[@class="releasetime"]/text()')

完整程序代码

上述内容介绍了编写程序时用到的 Xpath 表达式,下面正式编写爬虫程序,代码如下所示:

  1. # coding:utf8
  2. import requests
  3. from lxml import etree
  4. from ua_info import ua_list
  5. import random
  6.  
  7. class MaoyanSpider(object):
  8. def __init__(self):
  9. self.url='https://maoyan.com/board/4?offset=50'
  10. self.headers={'User-Agent':random.choice(ua_list)}
  11.  
  12.  
  13. def save_html(self):
  14. html=requests.get(url=self.url,headers=self.headers).text
  15. #jiexi
  16. parse_html=etree.HTML(html)
  17.  
  18. # 基准 xpath 表达式,匹配10个<dd>节点对象
  19. dd_list=parse_html.xpath('//dl[@class="board-wrapper"]/dd') #列表放10个dd
  20. print(dd_list)
  21. # .// 表示dd节点的所有子节点后代节点
  22. # 构建item空字典将提取的数据放入其中
  23. item={}
  24. for dd in dd_list:
  25. # 处理字典数据,注意xpath表达式匹配结果是一个列表,因此需要索引[0]提取数据
  26. item['name']=dd.xpath('.//p[@class="name"]/a/text()')[0].strip()
  27. item['star']=dd.xpath('.//p[@class="star"]/text()')[0].strip()
  28. item['time']=dd.xpath('.//p[@class="releasetime"]/text()')[0].strip()
  29. #输出数据
  30. print(item)
  31.  
  32. def run(self):
  33. self.save_html()
  34.  
  35. if __name__ == '__main__':
  36. spider=MaoyanSpider()
  37. spider.run()

输出结果如下:

 

posted @ 2022-08-01 13:03  随遇而安==  阅读(56)  评论(0编辑  收藏  举报