网络爬虫 - scrapy深入(十五)


一、Item数据结构

Item是保存爬取数据的容器,它的使用方法和字典类似。不过,相比字典, Item提供了额外的保护机制,可以避免拼写错误或者定义
字段错误。

创建Item需要继承scrapy.Item类,并且定义类型为scrapy.Field的字段。在创建项目开始的时候Item文件是这样的。

import scrapy
class TutorialItem(scrapy.Item):
    # define the fields for your item here like:
    # 参照下面这个参数定义你的字段
    # name = scrapy.Field()
    pass

在保存数据的时候可以每次初始化一个字典等格式,但是最方便,最好的保存方式就是使用 Scrapy 自带的 Item 数据结构了。

我们学习了从页面中提取数据的方法,接下来学习如何封装爬取到的数据。应该用怎样的数据结构来维护这些零散的信息字段呢?最容易想到是使用Python字典(dict)。

回顾之前的代码

class QuotesSpider(scrapy.Spider):
    name = 'quotes'
    allowed_domains = ['toscrape.com']
    start_urls = ['http://quotes.toscrape.com/']
    def parse(self, response):
        quotes = response.css('.quote')
         for quote in quotes:
            text = quote.css('.text::text').get()
            author = quote.css('.author::text').get()
            tags = quote.css('.tag::text').getall()
            yield {
   
                'text': text,
                'author': author,
                'tags': tags,
           }

在该案例中,我们便使用了Python字典存储一条数据的信息,但字典可能有以下缺点:
(1)无法一目了然地了解数据中包含哪些字段,影响代码可读性。
(2)缺乏对字段名字的检测,容易因程序员的笔误而出错。
(3)不便于携带元数据(传递给其他组件的信息)。

为解决上述问题,在Scrapy中可以使用自定义的Item类封装爬取到的数据。

1. Item和Field

Scrapy提供了以下两个类,用户可以使用它们自定义数据类(如书籍信息),封装爬取到的数据:

1. Item基类

数据结构的基类,在items.py中定义数据结构时,需要继承自该基类。

2. Field类

用来描述自定义数据类包含哪些字段(如name、price等)。
自定义一个数据类,只需继承Item,并创建一系列Field对象的类属性即可。
以定义书籍信息 quote 为例,它包含个字段,分别为书的名字text、author和tags,代码如下:

# 特殊的字典结构 可以在scrapy中传递数据
class TutorialItem(scrapy.Item):
    # Field 字段
    # 就是类似于产生一个类似字典格式的数据 拥有字典的一些属性
    # 字段默认为空
    # 我们可以通过实例化 像着键赋值 但是如果没有写这个键 就不能赋值 但是字典可以
    text = scrapy.Field()
    author = scrapy.Field()
    tags = scrapy.Field()

Item支持字典接口,因此 TutorialItem 在使用上和Python字典类似。

对字段进行赋值时,TutorialItem 内部会对字段名进行检测,如果赋值一个没有定义的字段,就会抛出异常(防止因用户粗心而导致错误)

2. 多个item处理

from NcepuSpider.items import ArticleViewsCountItem
from NcepuSpider.items import ArticleBodyItem
from NcepuSpider.items import NcepuNewsSpiderItem


def process_item(self, item, spider):
    # 使用isinstance然后通过if判断方式进行items类别筛选
    # 写入json文件
	if isinstance(item, ArticleViewsCountItem):
        pass
    elif isinstance(item, ArticleBodyItem):
        pass
    elif isinstance(item, NcepuNewsSpiderItem):
        pass
    return item

二、Item Pipeline

当 spider 获取到数据(item)之后,就会将数据发送到 ItemPipeline,Item Pipeline 通过顺序执行的几个组件处理它。

在Scrapy中,Item Pipeline是处理数据的组件,一个Item Pipeline就是一个包含特定接口的类,通常只负责一种功能的数据
处理,在一个项目中可以同时启用多个Item Pipeline,它们按指定次序级联起来,形成一条数据处理流水线。

Item Pipeline 的典型用途是:

  1. 清理HTML数据
  2. 验证的数据(检查项目是否包含某些字段)
  3. 进行数据的保存

1. Item Pipeline 使用

Scrapy 提供了 pipeline 模块来执行保存数据的操作。在创建的 Scrapy 项目中自动创建了一个 pipeline.py 文件,同时创建了一个默认的 Pipeline 类:

class TutorialPipeline(object):
    def process_item(self, item, spider):
        return item

在这个类中,有个方法叫 process_item() 方法,每个 Pipeline 都需要调用该方法。

process_item() 方法必须返回一个字典数据。默认有两个参数。如果把 Item 删除了那就不会再调用其他 Pipeline 方法了。

参数:

  1. item ( Item 对象 dict)
  2. spider (Spider 对象)

既然有了数据,那么就可以保存了:

class Qd03EnglishPipeline:
    def process_item(self, item, spider):
        print('item_info_2', item)
        with open('english.csv', mode='a', encoding='utf-8') as f:
            f.write(item['title'] + ',' + item['info'] + ',' + item['img_url'])
            f.write('\n')
        return item

2. 启用 Item Pipeline组件

只是上面定义方法还不行,还要激活该组件,也就是激活管道文件才能保存数据。激活是在配置文件setteings.py文件中激活,在
配置文件中找到如下变量值取消注释:

ITEM_PIPELINES = {
   
   'qd_03_english.pipelines.Qd03EnglishPipeline':300,
}

重点:
在上图中的字典结构的配置中,键是管道文件所在的路径,值是该管道文件的激活顺序,数字越小代表越早激活 。因为有时候会有多个管道文件。

完整的 item pipeline

import something

class SomethingPipeline(object):
    def __init__(self):    
        ## 可选实现,做参数初始化等
        ## doing something
        pass
    
    def open_spider(self, spider):
        ## spider (Spider 对象) – 被开启的spider
        ## 可选实现,当spider被开启时,这个方法被调用。
        pass
    
    def process_item(self, item, spider):
        ## item (Item 对象) – 被爬取的item
        ## spider (Spider 对象) – 爬取该item的spider
        ## 这个方法必须实现,每个item pipeline 组件都需要调用该方法,
        ## 这个方法必须返回一个 Item 对象,被丢弃的item将不会被之后的pipeline组件所处理。
        return item
        
    def close_spider(self, spider):
        ## spider (Spider 对象) – 被关闭的spider
        ## 可选实现,当spider被关闭时,这个方法被调用
        pass

写入JSON文件

class JSONPipeline:
    def __init__(self):
    	 self.f = open('data.json'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俾翻个牛B我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值