Item Pipeline简介
在Scrapy中, ItemPipeline是处理数据的组件, 一个Item Pipeline就是一个包含特定接口的类, 通常只负责一种功能的数据处理, 在一个项目中可以同时启用多个Item Pipeline, 它们按指定次序级联起来, 形成一条数据处理流水线。
以下是Item Pipeline的几种典型应用:
● 清洗数据。
● 验证数据的有效性。
● 过滤掉重复的数据。
● 将数据存入数据库。
实现Item Pipiline
在创建一个Scrapy项目时, 会自动生成一个pipelines.py文件,它用来放置用户自定义的Item Pipeline。
一个Item Pipeline不需要继承特定基类, 只需要实现某些特定方法, 例如process_item、 open_spider、close_spider。
一个Item Pipeline必须实现一个process_item(item,spider)方法, 该方法用来处理每一项由Spider爬取到的数据, 其中的两个参数:
- Item 爬取到的一项数据(Item或字典)
- Spider 爬取此项数据的Spider对象。
process_item方法是Item Pipeline的核心, 对该方法还需再做两点补充说明:
- 如果process_item在处理某项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对象。
启用Item Pipeline
在Scrapy中, Item Pipeline是可选的组件, 想要启用某个(或某些) Item Pipeline, 需要在配置文件settings.py中进行配置:
ITEM_PIPELINES = {
'example.pipelines.PriceConverterPipeline': 300,
}
ITEM_PIPELINES是一个字典, 我们把想要启用的ItemPipeline添加到这个字典中, 其中每一项的键是每一个ItemPipeline类的导入路径, 值是一个0~1000的数字, 同时启用多个Item Pipeline时, Scrapy根据这些数值决定各Item Pipeline处理数据的先后次序, 数值小的在前。
英镑兑换人民币例子
在pipelines.py中创建 类PriceConverterPipeline,然后编辑process_item()函数。
from scrapy.exceptions import DropItem
from scrapy.item import Item
#处理数据
class PriceConverterPipeline(object):
#英镑兑换人民币汇率
exchange_rate=8.5309
def process_item(self,item,spider):
#提取item的price字段
#去掉前面的英镑符号,转换为float类型,乘以汇率
price =float(item['price'][1:])*self.exchange_rate
#保留两位小数,赋值回item的price字段
item['price']='Y%.2f'%price
return item
再编辑settings.py文件,添加ITEM_PIPELINE
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'example.pipelines.PriceConverterPipeline': 300,
}
过滤重复数据例子
在pipelines.py中创建 类DuplicatesPipeline,然后编辑process_item()函数。
from scrapy.exceptions import DropItem
from scrapy.item import Item
#去重复数据
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文件,添加ITEM_PIPELINE
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'example.pipelines.PriceConverterPipeline': 300,
'example.pipelines.DuplicatesPipeline': 350,
}