一、Item Pipeline简介
Item
Pipeline的主要责任是负责处理爬虫从网页中抽取的Item,它的主要任务是清晰、验证和存储数据。
当页面被爬虫解析后,将被发送到Item管道,并经过几个特定的次序处理数据。
每个初始Item管道的组件都是由一个简单的方法组成的Python类。 如下所示:
1 2 3
| class DemoPipeline(object): def process_item(self, item, spider): return item
|
但是我们没有具体定义,因此执行爬虫并不会输出结果。
他们获取了Item并执行他们的方法,同时他们还需要确定的是是否需要在Item管道中继续执行下一步或是直接丢弃掉不处理。
****** ### 二、Item管道的通常执行过程 + 清理HTML数据 +
验证解析到的数据(检查Item是否包含必要的字段) +
检查是否是重复数据(如果重复就删除) +
将解析到的数据存储到数据库中 ******
###
三、编写pineline规范
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class DemoPipeline(object): def __init__(self): pass
def process_item(self, item, spider): pass return item
def open_spider(self, spider): pass
def close_spider(self, spider): pass
|
注意:
>
在settings.py文件中默认是关闭pipeline管道的。因此如果要使用自定义的管道文件,还需要在settings.py文件中启用pipeline。如果你在pipeline定义了多个管道的类,在settings.py中可以写多个pipeline的类,通过后面的数字的优先级区分哪个先执行。优先级的取值范围为0到1000,数值越小优先级越高。
例如:
1 2 3 4 5 6
|
ITEM_PIPELINES = { 'Demo.pipelines.DemoPipeline1': 300, 'Demo.pipelines.DemoPipeline2': 100, }
|
上述DemoPipeline2先执行。 ****** ### 四、Item
Pipeline例子 #### 4.1 数据清理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
from scrapy.exceptions import DropItem
class DemoPipeline(object):
vat_factor = 1.15
def process_item(self,item,spider): if item['price']: if item['price_excludes_vat']: item['price'] = item['price'] * self.vat_factor return item else: raise DropItem("Missing price in %s" % item)
|
#### 4.2 把Item写入Json文件
还是之前的项目Demo, 我们直接修改
pipelines.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import json
class DemoPipeline(object): def __init__(self): self.fp = open('C:\QzmVc1\Code\PyCharm\Python_Project\Python_Spider\Spider_Test1\Demo\scrapy.json','wb')
def process_item(self,item,spider): data = json.dumps(dict(item),ensure_ascii=False) self.fp.write(data.encode('utf-8')) return item def close_spider(self,spider): self.fp.close()
|
scrapy.json文件内容:
有的时候真的不能只看不练,当自己真正上手写的时候,才会发现自己的基础是那么差,漏洞百出。这里写的时候又碰到N多个坑,慢慢来吧,唉…
我同时也会把这些坑加入到我的这篇博客:Scrapy框架之细数到目前为止我遇到的坑
坑1:json.dumps的参数ensure_ascii=False:
在使用json.dumps时要注意一个问题
1 2 3 4 5 6
| >>> import json >>> print json.dumps('中国')
输出:"\u4e2d\u56fd" 输出的会是 '中国' 中的ascii 字符码,而不是真正的中文。
|
因为json.dumps
序列化时对中文默认使用的ascii编码.想输出真正的中文需要指定ensure_ascii=False;
坑2:中文保存到json文件中产生乱码
如上述代码所示转换为’UTF-8’编码,因为str.encode返回值是一个bytes对象,因此打开文件的方式要写成
‘wb’ 。 也可以通过在settings.py中添加如下代码:
FEED_EXPORT_ENCODING = ‘UTF-8’
4.3 删除重复数据
一个用于去重的过滤器,丢弃那些已经被处理过的item。假设item有一个唯一的id,但是我们spider返回的多个item中包含了相同的id,去重方法如下:这里初始化了一个集合,每次判断id是否在集合中已经存在,从而做到去重的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from scrapy.exceptions import DropItem
class DuplicatesPipeline(object):
def __init__(self): self.ids_seen = set()
def process_item(self, item, spider): if item['id'] in self.ids_seen: raise DropItem("Duplicate item found: %s" % item) else: self.ids_seen.add(item['id']) return item
|
4.4 将数据写入数据库
见下一章 ******
五、激活Item Pipeline组件
在settings.py文件中,往ITEM_PIPELINES中添加项目管道的类名,就可以激活项目管道组件,如:
1 2 3 4
| ITEM_PIPELINES = { 'Demo.pipelines.DemoPipeline1': 300, 'Demo.pipelines.DemoPipeline2': 100, }
|
整数值通常设置在0-1000之间,数值越低代表优先级越高。