Scrapy之ItemPipeline

 建议前往--Scrapy之ItemPipeline
上一篇文章中介绍了ItemLoader的用法和一些API,知道了ItemLoader在Downloader下载器中的作用“解决数据非结的缺陷,保证数据的进入Item的正确性;对数据进行自定义化的处理‘累加,去除多余元素’等等,完成了数据的第一部的清洗工作。今天,Spider想要更加健壮一些,相对数据查重,将数据写入Json文件或导入MongoDB数据库中去。这里,就是数据的第二部的清洗工作。
<!--more--->


----------
# Item Pipeline的构成

### process_item(self, item, spider)
每一个Pipeline组件即类中,这个函数是必须存在的,我们所做的数据查重,数据库导入的主体动作全部是在这里完成的。(没有这个函数,就不是一个完整的Pipeline组件)。其将返回一个带有数据的`Dict`,`Item`,或是`DropItem`异常。异常处理后`item`将不会被继续处理。

### open_spider(self, spider)
此函数就显而易见了,在Spider被开启时,这个方法自动被调用。我们可以设置在Spider开启时,什么样的动作被随之一起开启,比如数据库的连接操作。

### close_spider(self, spider)
在Spider被关闭时,这个方法自动被调用。同样,我们设置随之关闭的动作,比如数据库的断开操作。

### from_crawler(cls, crawler)
看到`cls`,很明显,这是个类方法。它的作用时送Setting文件中,寻找到相对应的数据,然后挂载到Spider中去,即让初始的Spider带着一些信息,以达到某种目的。比如数据库的远程地址的主机信息,端口信息,这样Spider就知道该将爬取的数据存到哪台PC机上了。


----------
# ItemPipelie Json格式写出组件

位置:`Pipeline.py`

```python
import json
import codecs
# 导入相应的库

class JsonWriterPipeline(object):

def __init__(self):
# 利用codecs打开一个'data.sjon'文件,'wb'即可读又可写,编码格式为'utf-8'
self.file = codecs.open('data1.json', 'wb', encoding='utf-8')

# 主体代码:
def process_item(self, item, spider):
# 这里特别说明:'ensure_ascii=False'关闭ASCII编码方式,不然会出现乱码的情况
line = json.dumps(dict(item), ensure_ascii=False) + ' '
# 将dict后的数据写入文件
self.file.write(line)
# 返回Item
return item
```

位置:`Settings.py`
```python
ITEM_PIPELINES = {
#'myproject.pipelines.MyProjectPipeline': 10,
'myproject.pipelines.JsonWriterPipeline': 11, # 开启Pipeline组件的相关功能
}
```

# ItemPipelie 写入MongoDB组件

位置:`Pipeline.py`

```python
import pymongo


class MongoWritePipeline(object):
# 集合的名称
collection = 'scrapy_items'

# 初始化主机地址和数据库名称
def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db

# 从Settings.py中获取主机地址和数据库名称挂载到Spider
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DATABASE', 'item')
)

# 当Spider启动时,自动连接到相对应的主机的MongoDB
def open_spider(self, spider):
# 启动l
self.client = MongoClient(self.mongo_uri)
# 获取数据库
self.db = self.client[self.mongo_db]

# 当Spdier关闭时,断开MongoDB
def close_spider(self, spider):
self.client.close()

# 主体代码
def process_item(self, item, spider):
# 将Dict化的数据insert入collection集合中
self.db[self.collection].insert(dict(item))
return item
```

位置:`Settings.py`
```python
ITEM_PIPELINES = {
#'myproject.pipelines.MyProjectPipeline': 10,
'myproject.pipelines.MongoWritePipeline': 12,
}
```

# ItemPipeline 查重组件

位置:`Pipeline.py`


```python
from scrapy.exceptions import DropItem

class DuplicatesPipeline(object):

def __init__(self):
# 设置一个set()变量的属性
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
```

经过上面的Pipeline组件的构造,编写的Spider又更加的健壮了,不在是以前那个简单头脑的Spider了。


----------

原文地址:https://www.cnblogs.com/7750-13/p/8961494.html