如何使用scrapy中的ItemLoader提取数据

1. 简述

我们在用scrapy爬取数据时,首先就要明确我们要爬取什么数据。scrapy提供了Item对象这种简单的容器,我们可以通过Item定义提取数据的格式,需要爬取哪些字段,其提供了类似于字典的API以及用于声明可用字段的简单语法。如下所示:
下面以爬取伯乐在线文章详情页为范例:http://blog.jobbole.com/all-posts/

如何使用scrapy中的ItemLoader提取数据

# 文件items.py
# Item使用简单的class定义语法以及 Field 对象来声明。
import scrapy

class articleDetailItem(scrapy.Item):
 # 标题
 title = scrapy.Field()
 # 文章创建时间
 create_date = scrapy.Field()
 # 文章链接地址
 url = scrapy.Field()
 # url经过md5映射后的值
 url_object_id = scrapy.Field()
 # 文章中图片地址
 front_image_url = scrapy.Field()
 # 文件下载后本地保存的地址
 front_image_path = scrapy.Field()
 # 赞的个数
 praise_nums = scrapy.Field()
 # 评论数
 comment_nums = scrapy.Field()
 # 收藏数
 fav_nums = scrapy.Field()
 # 所有标签
 tags = scrapy.Field()
 # 文章内容
 content = scrapy.Field(serializer = str)

Item字段说明:

  • Field 对象指明了每个字段的元数据(metadata)。例如上面例子中 content 字段中指明了该字段的序列化函数为str。
  • 可以为每个字段指明任何类型的元数据。Field 对象对接受的值没有任何限制。Field 对象中保存的每个键可以由多个组件使用,并且只有这些组件知道这个键的存在。设置 Field 对象的主要目的就是在一个地方定义好所有的元数据。
  • 需要注意的是,用来声明item的 Field 对象并没有被赋值为class的属性。 不过可以通过 Item.fields 属性进行访问。

然后在spider.py中,按照一定的规则来进行数据的提取,如下:

# 文件 boleSpider.py
from ArticleSpider.items import articleDetailItem

#...........此处省略..........
def parseArticelDetail(self, response):
 articleObject = articleDetailItem()
 # 提取出的内容是:6 收藏
 fav_nums = response.xpath("//span[contains(@class, 'bookmark-btn')]/text()").extract()[0]
 # 用正则表达式提取其中的数字6
 match_re = re.match(".*?(\d+).*", fav_nums)
 if match_re:
  fav_nums = match_re.group(1)
 else:
  fav_nums = 0

但是当项目很大,提取的字段数以百计,那么各种提取规则会越来越多,按照这种方式来做,维护的工作将会是一场噩梦!
所以scrapy就提供了ItemLoader这样一个容器,在这个容器里面可以配置item中各个字段的提取规则。可以通过函数分析原始数据,并对Item字段进行赋值,非常的便捷。

可以这么来看 Item 和 Itemloader:Item提供保存抓取到数据的容器,而 Itemloader提供的是填充容器的机制。

Itemloader提供的是一种灵活,高效的机制,可以更方便的被spider或source format (HTML, XML, etc)扩展并重写,更易于维护,尤其是分析规则特别复杂繁多的时候。

2. 环境

  • 系统:win7
  • Scrapy 1.4.0
  • python 3.6.1

3. ItemLoader使用步骤

3.1. 实例化ItemLoader对象

# 文件 boleSpider.py
from scrapy.loader import ItemLoader

要使用Itemloader,必须先将它实例化。可以使用类似字典的对象或者我们之前定义的Item对象来进行实例化。

# 文件 boleSpider.py 
import scrapy
from scrapy.loader import ItemLoader

# 如上面所示,我们首先在items.py中定义了一个articleDetailItem类(继承自scrapy.Item),用于保存我们抓取到的数据

 # 解析函数
 def parse_detail(self, response):
  # 需要实例化ItemLoader, 注意第一个参数必须是实例化的对象...
  atricleItemLoader = ItemLoader(item = articleDetailItem(), response=response)
  # 调用xpath选择器,提起title信息
  atricleItemLoader.add_xpath('title', '//div[@class="entry-header"]/h1/text()')

  # 将提取好的数据load出来
  articleInfo = atricleItemLoader.load_item()
  # 输出:articleInfo = {'title': ['在 Linux 中自动配置 IPv6 地址']}
  print(f"articleInfo = {articleInfo}")

参数说明:重要的参数有两个

  • 第一个参数:item对象, 传递进来的 Item是之前定义的,也可以是一个类似字典的对象。特别需要注意的是,传递的是一个实例,不是类名。……(当然不使用对象也可以,当不用对象进行实例化的时候,Item会自动使用ItemLoader.default_item_class 属性中指定的Item 类在Item Loader constructor中实例化)

    如何使用scrapy中的ItemLoader提取数据

扫一扫手机访问