第五章 使用Item Pipeline处理数据

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

Item Pipeline的几种典型应用:
- 清洗数据
- 验证数据的有效性
- 过滤掉重复的数据
- 将数据存入数据库

1. Item Pipeline

在之前的example项目中,我们爬取到的书籍价格是以英镑为单位的,如果我们希望爬取到的书价是人民币价格呢?
就需要根据汇率算出人民币价格,此时可以实现一个价格转换的Item Pipeline来完成这个工作

1. 实现Item Pipeline

在创建项目时,会自动生成一个pipelines.py文件,用来放置用户自定义的Item Pipeline

class PriceConverterPipeline(object):
    # 英镑兑换人民币汇率
    exchange_rate = 8.5309

    def process_item(self, item, spider):
        # 提取item的price字段
        # 去掉前面的英镑符号,转换为float类型,乘以汇率
        price = float(item['price'][1:]) * self.exchange_rate
        # 保留2位小数,赋值回item的price字段
        item['price'] = '¥%.2f' % price
        return item
  • 一个Item Pipeline 不需要继承特定基类,只需要实现某些特定的方法,例如,process_item , open_spider , close_spider

  • 必须实现一个 process_item(item,spider)方法,该方法用来处理每一项由Spider爬取到的数据,其中的两个参数:

    item        爬取到的一项数据
    spider      爬取此项数据的Spider对象
    

可以看出, process_item 方法是Item Pipeline的核心

  • 如果process_item在处理某项item时返回了一项数据,返回的数据会传递给下一级 Item Pipeline(如果有)继续处理
  • 如果process_item 在处理某项item时抛出(raise)一个DropItem异常(scrapy.exceptions.DropItem),该项item便会抛弃,不会传递给后面的Item Pipeline继续处理,也不会导出到文件.通常,我们在检测到无效数据或想要过滤数据时,抛出DropItem异常

除了必须实现的process_item方法外,还有3个比较常用的方法

  • open_spider(self,spider)

    Spider打开时(处理数据前)回调该方法,通常该方法用于在处理数据之前完成某些初始化工作,如连接数据库
    
  • close_spider(self,spider)

    Spider关闭时(处理数据后)回调该方法,通常该方法用于在处理完成所有数据之后完成某些清理工作,如关闭数据库
    
  • from_crawler(cls,crawler)

    创建Item Pipeline对象时回调该类方法.通常,在该方法中通过crawler.settings读取配置,根据配置创建ItemPipeline对象
    

2. 启用Item Pipeline

Item Pipeline是可选的组件,想要启动某Item Pipeline,需要在配置文件settings.py 中进行配置

ITEM_PIPELINES = {
   'example.pipelines.PriceConverterPipeline': 300,
}

ITEM_PIPELINES 是一个字典,每一项的键是每一个Item Pipeline类的导入路径,值是0-1000的数字,同时启用多个Item Pipeline时,Scrapy根据这些数值决定各个Item Pipeline 处理数据的先后次序,数值小的在前

重新运行爬虫,观察结果

scrapy crawl books -o books2.csv

2. 更多栗子

1. 过滤重复数据

class DuplicatesPipeline(object):
    def __init__(self):
        self.book_set = set()

    def process_item(self, item, spider):
        name = item['name']
        if name in self.book_set:
            raise DropItem("Duplicate book found:%s" % item)
        self.book_set.add(name)
        return item

修改 settings.py,重新运行,发现比之前的数据少了一条,对比发现,确实过滤掉重复数据了

2. 将数据存入MongoDB

未完待续

  • 0
    点赞
  • 2
    收藏 更改收藏夹
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

三丁目の夕阳下的白菜

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值