一. Itme Pipeline 的用法
Item Pipeline 是项目管道,它的调用发生在 Spider 产生 Item 之后。当 Spider 解析完 Response 之后,Item 就会传递到 Item Pipeline,被定义的 Item Pipeline 组件会顺次调用,完成一连串的处理过程,比如数据清洗、存储等。 它的主要功能有:
- 清洗 HTML 数据
- 验证爬取数据,检查爬取字段
- 查重并丢弃重复内容
- 将爬取结果储存到数据库
1. 实现 Item Pipeline
在创建一个 Scrapy 项目时,会自动生成一个 pipelines.py
文件,它用来放置用户自定义的Item Pipeline。例如在toscrapy 项目的 pipelines.py
中实现 PriceConverterPipeline
,代码如下:
class PriceConverterPipeline(object):
exchange_rate = 8.5309
def process_item(self, item, spider):
price = float(item['price'][1:])*self.exchange_rate
item['price'] = '¥%.2f'%price
return item
上述代码中的 process_item
方法实现非常简单,将书籍的英镑价格转换为浮点数,乘以汇率并保留2位小数,然后赋值回 item 的 price 字段,最后返回被处理过的 item。
在 pipelines.py
中编写完成 Item Pipeline 之后,就要在 settings.py 中进行配置。在 Scrapy 中,Item Pipeline 是可选的组件,想要启用某个(或某些)Item Pipeline,则在配置文件 settings.py 中进行如下配置:
ITEM_PIPELINES = {
'toscrapy.pipelines.PriceConverterPipeline': 300,}
将原代码取消注释,并将其中的 ToscrapyPipeline
改为 PriceConverterPipeline
。ITEM_PIPELINES 是一个字典,我们把想要启用的 Item Pipeline 添加到这个字典中,其中每一项的键是每一个 Item Pipeline 类的导入路径,值是一个0~1000的数字,同时启用多个 Item Pipeline 时,Scrapy 根据这些数值决定各 Item Pipeline 处理数据的先后次序,数值小的在前。
启用 PriceConverterPipeline
后,重新运行爬虫,运行结果如下:
(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Simple_Case/toscrapy/toscrapy$ scrapy crawl books -o books.csv
......
(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Simple_Case/toscrapy/toscrapy$ head -5 books.csv
name,price
A Light in the Attic,¥441.64
Tipping the Velvet,¥458.45
Soumission,¥427.40
Sharp Objects,¥407.95
使用 PriceConverterPipeline
对数据进行处理后,books.csv 中的书价转换成了人民币价格。
对于 Item Pipeline 的核心函数 process_item
方法及其他三个方法的详细介绍如下所述。
2. 核心方法
我们可以自定义 Item Pipeline,只需要实现指定的方法就好,其中必须要实现的一个方法是:
- process_item(item, spider)
另外还有几个比较实用的方法,它们分别是:
- open_spider(spider)
- close_spider(spider)
- from_crawler(cls, crawler)
下面我们对这几个方法的用法作下详细的介绍:
(1)process_item(item, spider)
process_item () 是必须要实现的方法,被定义的 Item Pipeline 会默认调用这个方法对 Item 进行处理。比如,我们可以进行数据处理或者将数据写入到数据库等操作。它必须返回 Item 类型的值或者抛出一个 DropItem 异常。 process_item () 方法的参数有如下两个。
- item:是 Item 对象,即被处理的 Item
- spider:是 Spider 对象,即生成该 Item 的 Spider
下面对该方法的返回类型归纳如下:
- 如果返回的是 Item 对象,那么此 Item 会接着被低优先级的 Item Pipeline 的 process_item () 方法进行处理,直到所有的方法被调用完毕;
- 如果抛出的是 DropItem 异常,那么此 Item 就会被丢弃,不再进行处理。
如果 process_item
在处理某项 item 时返回了一项数据(Item 或字典),返回的数据会递送给下一级 Item Pipeline(如果有)继续处理。如果 process_item
在处理某项 item
时抛出一个 DropItem 异常(scrapy.exceptions.DropItem),该项 item 便会被抛弃,不再递送给后面的 Item Pipeline 继续处理,也不会导出到文件。通常,我们在检测到无效数据或想要过滤数据时,抛出DropItem异常。
(2)open_spider(self, spider)
open_spider () 方法是在 Spider 开启的时候被自动调用的,在这里我们可以做一些初始化操作,如开启数据库连接等。其中参数 spider 就是被开启的 Spider 对象。
(3)close_spider(spider)
close_spider () 方法是在 Spider 关闭的时候自动调用的,在这里我们可以做一些收尾工作,如关闭数据库连接等,其中参数 spider 就是被关闭的 Spider 对象。
(4)from_crawler(cls, crawler)
from_crawler () 方法是一个类方法,用 @classmethod 标识,是一种依赖注入的方式。它的参数是 crawler,通过 crawler 对象,我们可以拿到 Scrapy 的所有核心组件,如全局配置的每个信息,然后创建一个 Pipeline 实例。参数 cls 就是 Class,最后返回一个 Class 实例。 下面我们用一个实例来加深对 Item Pipeline 用法的理解。
3. 如何使用 Item Pipeline 处理数据
以 toscrapy 项目为例,我们说明 Item Pipeline 的两种使用场景:数据去重和数据存储在 MongoDB 。
(1)数据去重
为了确保在 books 爬虫中爬取到的书籍信息中没有重复项,可以实现一个去重 Item Pipeline。这里,我们就以书名作为主键(实际应以ISBN编号为主键,但是仅爬取了书名和价格)进行去重,实现 DuplicatesPipeline
代码如下:
from scrapy.exceptions import DropItem
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
对上述代码解释如下:
- 在 init 方法中增加构造器方法,在其中初始化用于对书名去重的集合。
- 在 process_item 方法中,先取出 item 的 name 字段,检查书名是否已在集合 book_set 中,如果存在,就是重复数据,抛出 DropItem 异常,将 item 抛弃;否则,将 item 的 name 字段存入集合,返回 item。
接下来测试DuplicatesPipeline。在配置文件 settings.py 中启用 DuplicatesPipeline
:
ITEM_PIPELINES = {
'toscrapy.pipelines.PriceConverterPipeline': 300,
'toscrapy.pipelines.DuplicatesPipeline': 350,
}
运行爬虫,对比结果:
(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Scrapy_Book/toscrapy/toscrapy$ scrapy crawl books -o book1.csv
......
(pyspider) pyvip@VIP:~/project/Python_Spider/Spider_Project/Scrapy_Book/toscrapy/toscrapy$ sed -n '2,$p' books1.csv | cat -n
1 A Light in the Attic,¥441.64
2 Tipping the Velvet,¥458.45
3 Soumission,¥427.4
4 Sharp Objects,¥407.95
......
987 Charlie and the Chocolate Factory (Charlie Bucket #1),¥194.93
988 Charity's Cross (Charles Towne Belles #4),¥351.81
989 Bright Lines,¥333.30
990 Bridget Jon