Scrapy提供了Item类。
Item对象是种简单的容器(类似于字典(dict,键值对)),保存爬取到得数据。
1、声明Item
Item使用简单的class定义语法和Filed对象来申明,例如:
from scrapy import Field,Item class Produce(Item): name=Field() price=Field() stock=Field()
2、Item Pipeline
当Item被spider抓取后,它被发送到Item管道(Item Pipeline),它通过顺序执行的几个组件来处理Item。
每个item pipeline组件(有时称为Item Pipeline)是实现了简单方法的python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或者被丢弃而不再进行处理。
以下是Item Pipeline的典型应用:
- 清洗HTML数据
- 验证爬取的数据(检查item包含某些字段)
- 查重(并丢弃)
- 将爬取结果保存到数据库中
3、编写自己的item pipeline
每个item pipeline组件是一个独立的python类,同时实现以下方法:
(1)process_item(self,item,spider)
每个Item Pipeline组件都会调用此方法。该方法必须:返回一个带数据的dict,或是返回一个Item(或任何后代类)对象,或是返回一个Twisted Deffered,或者抛出异常。被抛弃的Item不再被其他的Ppipeline组件处理。
参数:
- item (Item对象或一个dict)----->被爬取的item
- spider (Spider对象)----->爬取该item的spider
(2)open_spider(self,spider)
当spider被开启时,这个方法被调用。
参数:
- spider (Spider对象)----->被开启的spider
(3)close_spider(self,spider)
当spider被关闭时,这个方法被调用。
参数:
- spider (Spider对象)----->被关闭的spider
(4)from_crawl(cls,crawler)
如果存在,则调用此方法以从crawler创建pipeline实例。它必须返回一个新的pipeline实例。
crawler对象提供所有scrapy核心组件(如settings和signals)的访问,它是pipeline访问它们并将其功能挂钩到scrapy的一种方法。
参数:
- crawler (Crawler对象)----->使用此pipeline的crawler
4、Item Pipeline示例(在pipelines.py中编辑)
(4-1)验证价格,同时丢弃没有价格的item
说明:其调整了不包括增值税(price_excludes_vat属性)的那些item的price属性,并丢弃那些不包含price的item
from scrapy.exceptions import DropItem class PriceItem(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 {}".format(item))
(4-2)将item写入.json文件
说明:其将所有(从所有spider中)爬取到的item存储到一个独立的info.jl文件,每行包含一个序列化为json格式的item
import json class JsonWriterPipeline(object): def __init__(self): self.filename=open('info.json','a',encoding='utf-8') def process_item(self,item,spider): line=json.dumps(dict(item),ensure_ascii=False) self.filename.write(line) self.filename.write('\n') def close_spider(self,spider): self.filename.close()
(4-3)将item写入MongoDB数据库
说明:其将使用pymongo将item写入MongoDB。MongoDB中的配置在scrapy的settings.py中指定
假设settings.py中的配置如下:
ITEM_PIPELINES={'quotes.pipelines.QuotesPipeline':300,} MONGODB_HOST='127.0.0.1' #主机号 MONGODB_PORT=27017 #端口号 MONGODB_DBNAME='Quotes' #数据库名 MONGODB_SHEETNAME='mymj' #表名
在pipelines.py中操作:将item数据保存到数据库中
from scrapy.conf import settings
import pymongo
class QuotesPipelines(object):
def __init__(self):
self.host=settings['MONGODB_HOST']
self.port=settings['MONGODB_PORT']
self.dbname=settings['MONGODB_DBNAME']
self.sheetname=settings['MONGODB_SHEETNAME']
client=pymongo.MongoClient(host=self.host,port=self.port)
mydb=client[self.dbname]
self.post=mydb[self.sheetname]
def process_item(self,item,spider):
data=dict(item)
self.post.insert(data) #将数据存入到mongodb数据库中
return item
(4-4)去重
说明:用于查找重复的item并丢弃已处理的item过滤器。假设我们的item具有唯一的ID。
【但是:spider会返回具有相同id的多个item】
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("去重的item为{}".format(item)) else: self.ids_seen.add(item['id']) return item
5、激活一个Item Pipeline组件
要激活item pipeline,必须将其类添加到ITEM_PIPELINES设置中,如下:
ITEM_PIPELINES={ 'myproject.pipelines.PricePipeline':300, 'myproject.pipelines.JsonWriterPipeline':800, }
在此设置中分配给类的整数值确定它们运行的顺序:item按数字从低到高的顺序通过pipeline。【数字越低优先级越高】