Scrapy框架(四) 使用Pipeline处理数据(一)
一、Item Pipeline简介
Item
Pipeline的主要责任是负责处理爬虫从网页中抽取的Item,它的主要任务是清晰、验证和存储数据。
当页面被爬虫解析后,将被发送到Item管道,并经过几个特定的次序处理数据。
每个初始Item管道的组件都是由一个简单的方法组成的Python类。 如下所示:
1
2
3class DemoPipeline(object):
def process_item(self, item, spider):
return item1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class DemoPipeline(object):
def __init__(self):
pass
# 可选方法,用于做参数初始化等操作,常用于保存item到文件中穿件文件并打开时用到
# doing someting
def process_item(self, item, spider):
pass
return item #如果有下一个管道,为了传给下一个管道时用
# 参数item---被爬取的item
# 参数spider--爬取该item的spider
# 该方法process_item是必须的方法,必须返回一个Item对象或者抛出DropItem异常
def open_spider(self, spider):
pass
# 参数spider---被开启的spider
# 当spider被开启时,该方法open_spider会被调用
# 该方法open_spider为可选方法
def close_spider(self, spider):
pass
# 参数spider---被关闭的spider
# 当spider爬虫被关闭时,close_spider方法会被调用
# 该方法close_spider为可选方法
例如: 1
2
3
4
5
6# Configure item pipelines
# See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'Demo.pipelines.DemoPipeline1': 300,
'Demo.pipelines.DemoPipeline2': 100,
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 注:VAT:Value Added Tax(增值税)
# 以上代码可以过滤那些没有价格的产品,并且对那些不包括增值税产品的价格进行调整
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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 导入Json模块
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):
# 将item转换为json格式
data = json.dumps(dict(item),ensure_ascii=False)
# 写入json文件
self.fp.write(data.encode('utf-8'))
return item
def close_spider(self,spider):
# 关闭文件
self.fp.close()
有的时候真的不能只看不练,当自己真正上手写的时候,才会发现自己的基础是那么差,漏洞百出。这里写的时候又碰到N多个坑,慢慢来吧,唉…
我同时也会把这些坑加入到我的这篇博客:Scrapy框架之细数到目前为止我遇到的坑
坑1:json.dumps的参数ensure_ascii=False:
在使用json.dumps时要注意一个问题
因为json.dumps 序列化时对中文默认使用的ascii编码.想输出真正的中文需要指定ensure_ascii=False;
1
2
3
4
5
6 import json
print json.dumps('中国')
输出:"\u4e2d\u56fd"
输出的会是
'中国' 中的ascii 字符码,而不是真正的中文。
坑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
14from 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
4ITEM_PIPELINES = {
'Demo.pipelines.DemoPipeline1': 300,
'Demo.pipelines.DemoPipeline2': 100,
}