Item Pipeline
Item在spider中获取后,将传送到Item Pipeline中,执行对Item的后续处理。每个item pipeline组件实现了简单方法,它们接收item并执行一些操作,决定丢弃item还是让其通过pipeline。
item pipeline的作用:
- 清理HTML数据
- 验证爬取的数据(检查item包含的某些字段)
- 查重
- 保存将爬取到的数据
当然,你也可以编写自己的item pipeline,不过你需要实现以下方法:
process_item(item,spider)
每个item pipeline都需要调用该方法,并且返回一个Item对象或者抛出DropItem异常,item被丢弃后将不被pipeline处理。
参数: item(Item对象)-被爬取的item
spider(Spider对象)-爬取该是特么的spider
除此之外,还可以实现以下方法:
open_spider(spider):当spider开启时调用。
close_spider(spider):当spider关闭时调用。
ImagePipeline
scrapy用ImagePipeline提供了一种方便的方式下载和存储图片。
自定义ImagePipeline时,最重要的是重载get_media_requests(self,item,info)和item_completed(self,results,item,info)这两个函数。
get_media_requests(self,item,info):通过该函数为image_urls中的每一个url生成一个Request。
for url in item['image_url']:
self.default_headers['referer']=url
yield Request(url,headers=self.default_headers)
图片下载完毕后,处理结果会以二元组的方式返回给item_completed()函数。这个二元组定义为(success,image_info_or_failure)。其中,第一个元素表示图片是否下载成功,第二个元素是一个字典。
def item_completed(self, results, item, info):
image_paths = [x['path'] for ok, x in results if ok]
if not image_paths:
raise DropItem("Item contains no images")
item['image_paths'] = image_paths
return item
下面以爬取尤果网上的美女图片为例,说明整个过程。
1、item.py,添加image_url与name字段,代码如下:
import scrapy
class UgirlsItem(scrapy.Item):
# define the fields for your item here like:
image_url=scrapy.Field()
name=scrapy.Field()
2、在spider/ugirl.py 中写ImageSpider的代码
# -*- coding: utf-8 -*-
import scrapy
from scrapy import Request
from ..items import UgirlsItem
class UgirlSpider(scrapy.Spider):
name = 'ugirl'
allowed_domains = ['ugirls.com']
start_urls = []
for i in range(1,43):
start_urls.append('https://www.ugirls.com/Content/Page-%d.html'%(i))
def start_requests(self):
for url in self.start_urls:
yield Request(url=url,callback=self.parse)
def parse(self, response):
item=UgirlsItem()
name=response.xpath('//div[@class="magazine_info"]/h2/a/text()').extract()
image_url=response.xpath('//img[@class="magazine_img"]/@src').extract()
item['name']=name
item['image_url']=image_url
yield item`
3、在pipelines.py中自定义ImagePipeline的代码
# -*- coding: utf-8 -*-
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy.http import Request
class UgirlsPipeline(object):
def process_item(self, item, spider):
return item
class MyPipeline(ImagesPipeline):
def get_media_requests(self,item,info):
for image_url in item['image_url']:
yield Request(image_url,meta={'item':item,'index':item['image_url'].index(image_url)})
def item_completed(self,results,item,info):
image_paths=[x['path'] for ok, x in results if ok]
if not image_paths:
raise DropItem("Item contains no images")
item['image_paths'] = image_paths
return item
4、最后在settings.py中进行下载路径等配置。
ITEM_PIPELINES={
'ugirls.pipelines.MyPipeline':200,
'ugirls.pipelines.UgirlsPipeline':300,
}
IMAGES_STORE= r'D:\programing\Python\Crawler\scrapy\ugirls\\'
IMAGE_EXPIRES=90
ITEM_PIPELINES中定义了各个管道的执行顺序,值的范围通常为0-1000,数值越小越先执行;IMAGES_STORE定义了爬取数据的存储位置;IMAGE_EXPIRES=90表示90天内不会下载重复的数据。
最后执行scrapy crawl ugirl命令,爬取结果如下图所示:
这里只是简单的应用了ImagePipeline爬取图片的方便功能,我们还可以创建缩略图和对图片进行分类。