Item管道的主要责任是负责处理有蜘蛛从网页中抽取的Item,他的主要任务是清洗、验证和存储数据。
当页面被蜘蛛解析后,将被发送到Item管道,并通过几个特定的次序处理数据。
每一个Item管道的组件都是有一个简单的方法组成的Python类。
他们获取了Item并执行他们的方法,同时他们还须要肯定的是是否须要在Item管道中继续执行下一步或是直接丢弃掉不处理。html
清理HTML数据
验证解析到的数据(检查Item是否包含必要的字段)
检查是不是重复数据(若是重复就删除)
将解析到的数据存储到数据库中
每一个项目管道组件是一个Python类,必须实现如下方法:mongodb
process_item(self, item, spider)
对于每一个项目管道组件调用此方法。process_item() 必须返回一个带数据的dict,返回一个Item (或任何后代类)对象,返回一个Twisted Deferred或者raise DropItemexception。丢弃的项目再也不由其余管道组件处理。数据库
参数:json
另外,它们还能够实现如下方法:dom
# 当蜘蛛打开时调用此方法。 open_spider(self, spider) # 参数spider打开的蜘蛛 # 当蜘蛛关闭时调用此方法。 close_spider(self, spider) # 参数spider被关闭的蜘蛛 # 若是存在,则调用此类方法以从a建立流水线实例Crawler。它必须返回管道的新实例。Crawler对象提供对全部Scrapy核心组件(如设置和信号)的访问; 它是管道访问它们并将其功能挂钩到Scrapy中的一种方式。 from_crawler(cls, crawler) # 参数crawler(Crawlerobject) - 使用此管道的crawler
将抓取的items以json格式保存到文件中scrapy
从spider抓取到的items将被序列化为json格式,而且以每行一个item的形式被写入到items.jl文件中ide
import json class JsonWriterPipeline(object): def __init__(self): self.file = open('items.jl', 'wb') def process_item(self, item, spider): line = json.dumps(dict(item)) + "\n" self.file.write(line) return item
删除重复项函数
假设在spider中提取到的item有重复的id,那么咱们就能够在process_item函数中进行过滤url
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
激活ItemPipeline组件spa
在settings.py文件中,往ITEM_PIPELINES中添加项目管道的类名,就能够激活项目管道组件
ITEM_PIPELINES = { 'myproject.pipeline.PricePipeline': 300, 'myproject.pipeline.JsonWriterPipeline': 800, }
定义过滤字段
import scrapy class ImgpilelineproItem(scrapy.Item): # define the fields for your item here like: img_src = scrapy.Field()
只是用来获取图片的下载地址并提交至itme
import scrapy from imgPileLinePro.items import ImgpilelineproItem class ImgSpider(scrapy.Spider): name = 'img' # allowed_domains = ['www.xxx.com'] start_urls = ['http://pic.netbian.com/4kmeinv/'] url = 'http://pic.netbian.com/4kmeinv/index_%d.html' page = 2 def parse(self, response): li_list = response.xpath('//*[@id="main"]/div[3]/ul/li') for li in li_list: img_src = 'http://pic.netbian.com'+li.xpath('./a/img/@src').extract_first() item = ImgpilelineproItem() item['img_src'] = img_src yield item if self.page <= 2: # 爬取前两页 new_url = format(self.url%self.page) self.page += 1 yield scrapy.Request(url=new_url,callback=self.parse)
from scrapy.pipelines.images import ImagesPipeline import scrapy # 用来下载图片的管道类 class ImgPileLine(ImagesPipeline): #接收item且将item中存储的img_src进行请求发送 def get_media_requests(self,item,info): yield scrapy.Request(url=item['img_src']) #指定数据存储的路径(文件夹【在配置文件中指定】+图片名称【该方法中返回】) def file_path(self,request,response=None,info=None): img_name = request.url.split('/')[-1] return img_name #就是将item传递给下一个即将被执行的管道类 def item_completed(self,result,item,info): return item
# 指定文件的下载路径 IMAGES_STORE = './imgsLib' # 该文件会自动建立 # 启用管道 ITEM_PIPELINES = { 'imgPileLinePro.pipelines.ImgPileLine': 300, }
import pymongo class MongoPipeline(object): def __init__(self, mongo_uri, mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db @classmethod def from_crawler(cls, crawler): return cls( mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DATABASE', 'items') ) # 爬虫开始创建与mongodb的链接 def open_spider(self, spider): self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db] # 爬虫结束断开与mongodb的链接 def close_spider(self, spider): self.client.close() # 数据存储 def process_item(self, item, spider): # update 去重,以url_token为查找条件更新数据 self.db["user"].update({"url_token":item["url_token"]},{"$set":item},True) return item
MONGO_URI = "localhost" MONGO_DATABASE = "zhihu"