1、 初识Pipeline管道类
Pipeline管道类用于处理爬虫爬取的的Item数据,Item数据装配完成后,会提交给Pipeline管道类,Pipeline管道类会对Item数据进一步处理,包括数据的清洗、验证和存储。Pipeline管道类最终会决定爬取的Item数据是否保留或放弃。

爬虫提取的Item数据可以直接提交给Pipeline管道类,也可以通过ItemLoader类处理后再提交给Pipeline管道类。
Pipeline管道类会对Item数据进一步处理,包括数据的清洗和验证。若Item数据有问题,可以直接放弃该数据;若Item数据没有问题,则存储Item数据,可以以多种方式存储Item数据,根据爬虫的目的和需求,可以将Item数据存储到数据库,也可以存储为JSON数据或其它数据格式。
项目创建后,Scrapy框架会自动创建一个管道类,模块名称是pipelines.py,该管道类对Item数据不做任何处理,直接返回Item数据。pipelines.py代码如下:
from itemadapter import ItemAdapter class NewsbaiduPipeline: def process_item(self, item, spider): return item
从给出的代码也可以看出,NewsbaiduPipeline管道类对传入的Item数据不做任何处理,直接返回Item。若程序需要验证Item数据或存储到数据库,可以在这里添加相关代码。
Pipeline管道类是一个独立的Python类,该类必须实现下面的方法:
process_item(self, item, spider)
该方法用于处理传入的item数据项,并且必须返回一个Item对象,或者是处理后的Item对象,或者直接返回原item对象。若该方法没有返回Item对象,后续的Pipeline管道类将停止处理Item对象。
参数item是传入的Item实例对象。
参数spider是爬虫实例对象。
另外,Pipeline管道类也可以实现下面的三个方法:
open_spider(self, spider)
当爬虫启动时,该方法被调用。若程序需要在爬虫启动时,对Pipeline管道类进行初始化,可以在该方法内部进行。
close_spider(spider)
当爬虫关闭时,该方法被调用。若程序需要在爬虫关闭时,对管道类使用的资源做释放处理时,可以在该方法内部进行。
2、ItemAdapter适配器类
Scrapy默认创建的Pipeline管道类文件pipelines.py,使用到了ItemAdapter适配器类,ItemAdapter类是数据容器对象的包装器,它提供了一个公共接口以以适配不同类型的对象,而不管它们的底层实现如何。
ItemAdapter类主要支持dict字典对象和Scrapy Item数据对象的适配。
ItemAdapter类的构造方法如下表所示:

ItemAdapter实例对象可以像字典一样处理,字典的操作方法都可以用于ItemAdapter实例对象。另外,ItemAdapter实例对象也提供了下面的操作方法:

3、 启动Pipeline管道
Scrapy创建的爬虫项目包含了一个默认的Pipeline模块文件,模块文件名称是pipelines.py,该管道默认是关闭的,爬取数据的处理流程并不包括该管道。若启动该管道,需要修改配置文件ITEM_PIPELINES配置项,默认配置文件中ITEM_PIPELINES配置项是被注释掉的,把相关语句的注释去掉:
ITEM_PIPELINES = {
'newsbaidu.pipelines.NewsbaiduPipeline': 300,
}ITEM_PIPELINES配置项的值是字典对象,字典对象的每个元素是一个Pipeline管道类,可以添加多个Pipeline管道类。key是Pipeline管道类的类名称,value是一个整数,该整数确定了多个Pipeline管道类的运行顺序,Item数据将按照运行顺序依次被处理。通常将这些数字定义在0-1000范围内(0-1000随意设置,数值越低,对应的Pipeline管道类的运行顺序越靠前)。
在Pipeline管道类处理链中,链中的任一Pipeline管道类若没有返回处理后的Item数据项,Scrapy将停止处理Item数据项。
4、 项目输出CSV文件
Pipeline管道类NewsbaiduPipeline对Item数据不做任何处理,原样返回Item数据。
现在修改NewsbaiduPipeline类代码,将爬取的数据输出为CSV文件。
案例代码如下:
from itemadapter import ItemAdapter # 导入csv模块 import csv # 导入os模块 import os class NewsbaiduPipeline: # 定义构造方法,打开CSV文件 def __init__(self): # 定义CSV文件的存储路径 store_file = os.path.dirname(__file__) + '/items.csv' # 以a+模式创建CSV文件 self.file = open(store_file,'a+',newline='') # 实例化writer对象 self.writer = csv.writer(self.file) def process_item(self, item, spider): # 获得item数据项适配器 adapter = ItemAdapter(item) if adapter: # row为列表对象 row = [adapter['news_title'][0],adapter['news_link'][0]] # row写入CSV文件 self.writer.writerow(row) return item # 爬虫程序关闭时,该方法被调用 def close_spider(self,spider): # 关闭文件 self.file.close()
案例代码添加了构造方法__init__,在构造方法内部实例化CSV文件对象及csv模块的Writer实例对象。
案例代码重写了process_item方法,在方法内部获得item适配对象adapter,若adapter不为空,应用adapter适配对象构造列表对象,最后调用writer对象的writerow方法将item数据写入CSV文件。
案例代码添加了close_spider方法,该方法在爬虫关闭时被调用,当爬虫关闭时,关闭打开的CSV文件。