一、媒体管道(ImagesPipeline)是什么?
scrapy提供了专门下载的PIpeline,包含文件下载和图片下载。
二、为什么要有媒体管道?
简化操作,比如存储等。当然我们可以进行重写。
- 将下载图片转换成通用的JPG和RGB格式
- 避免重复下载
- 缩略图生成
- 图片大小过滤
- 异步下载
三、媒体管道的使用
1)使用
工作流程:
- 爬取一个Item,将图片的URLs放入image_urls字段
- 从Spider返回的Item,传递到Item Pipeline
- 当Item传递到ImagePipeline,将调用Scrapy 调度器和下载器完成image_urls中的url的调度和下载。
- 图片下载成功结束后,图片下载路径、url和校验和等信息会被填充到images字段中。
1、items.py定义特殊字段名 :
#内置的ImagePipeline会默认读取Item的image_urls字段,item.py 中只能写image_urls字段
image_urls = scrapy.Field() #固定
2、处理pipelines.py ,分为两种:
1、自定义pipeline,且让 类 继承ImagesPipeline,优势在于可以重写ImagePipeline类中的实现方法。
2、直接使用ImagePipeline类,简单但不够灵活。
方法一:
#这是自定义,优势在于可以重写ImagePipeline类中的实现方法,可以根据情况对照片进行分类;
'''
首先要复写父类的两个方法,一个是get_midia_requests(),构建request请求,然后交由下载器下载,第二个是item_completed(),当下载完毕后,默认会调用该方法,我们只需注意第二个results参数,他是一个由二元元祖组成的list,第一个值是一个布尔类型的值,用于判断图片是否下载成功,第二个值是关于图片的下载信息。
'''
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy import Request
class 类名(ImagesPipeline): #切记得继承ImagesPipeline
def get_media_requests(self, item, info):
for url in item['image_urls']:
yield Request(url)
def item_completed(self, results, item, info):
item['images'] = [x for ok, x in results if ok]
return item
def process_item(self,item,spider):
with open() as f:
f.write()
return item
方法二:
#在管道得开启 'scrapy.pipelines.images.ImagesPipeline' 这是媒体基础管道,可以试一下。且直接使用 ImagePipeline类,虽简单但不够灵活;所有的图片都是保存在 full文件夹下,而且图片名。
3、 配置settings中的ITEM_PIPELINES:
ITEM_PIPELINES={
#方法一: 管道开启
'项目名.piplines.自定义类名':1 , #后面数字1让它马上调用。
#方法二: 这是图片基础管道,scrapy写的,直接开启它就行了。
'scrapy.pipelines.images.ImagesPipeline': 1
}
4、媒体管道的一些设置:
在settings.py里添加,如IMAGES_STORE = 'IMG' #设置图片存储位置,这个必须得设</pre>
直接使用ImagePipeline类 , 所有的图片都是保存在 full文件夹下:
直接使用ImagePipeline类存储结果.png
2)媒体管道的一些设置:
代码语言:javascript复制在settings中添加就可以了
ITEM_PIPELINES = {‘scrapy.pipelines.images.ImagesPipeline’: 1} #启用
FILES_STORE = ‘/path/to/valid/dir’ #文件管道存放位置
IMAGES_STORE = ‘/path/to/valid/dir’ #图片管道存放位置
FILES_URLS_FIELD = ‘field_name_for_your_files_urls’ #自定义文件url字段
FILES_RESULT_FIELD = ‘field_name_for_your_processed_files’ #自定义结果字段
IMAGES_URLS_FIELD = ‘field_name_for_your_images_urls’ #自定义图片url字段
IMAGES_RESULT_FIELD = ‘field_name_for_your_processed_images’ #结果字段
FILES_EXPIRES = 90 #文件过期时间 默认90天
IMAGES_EXPIRES = 90 #图片过期时间 默认90天
IMAGES_THUMBS = {‘small’: (50, 50), ‘big’:(270, 270)} #缩略图尺寸
IMAGES_MIN_HEIGHT = 110 #过滤最小高度
IMAGES_MIN_WIDTH = 110 #过滤最小宽度
MEDIA_ALLOW_REDIRECTS = True #是否重定向</pre>
四、按例:爬取百度图片
代码语言:javascript复制1、item.py文件:定义item字段
import scrapy
class ImgPipelineItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
image_urls = scrapy.Field() #只要使用媒体管道,这个字段是固定设置的
2、spider.py文件:编写爬虫文件,解析源码,得到图片的url下载路径
import scrapy
import re
from ..items import ImgPipelineItem
class MediaSpider(scrapy.Spider):
name = 'media'
# allowed_domains = ['www.baidu.com']
start_urls = ['https://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gb18030&word=�˰���&fr=ala&ala=1&alatpl=adress&pos=0&hs=2&xthttps=111111']
def parse(self, response):
img_urls = re.findall('"thumbURL":"(.*?)"',response.text)[0:-1]
# print(img_urls)
item = ImgPipelineItem()
item['image_urls'] = img_urls
yield item
3、pipelines.py文件:对item里的数据进行处理,这里是调用调度器和下载器下载图片。
若直接使用ImagePipeline类 , 所以这里不用处理。
自定义:
import os
import scrapy
class ImgPipelinePipeline(ImagesPipeline):
# def get_media_requests(self, item, info):
def get_media_requests(self, item, info):
for file_url in item['image_urls']:
print("**********")
yield scrapy.Request(file_url)
def item_completed(self, results, item, info):
# image_paths = [x['path'] for ok, x in results if ok]
image_paths=[]
for ok,x in results:
if ok:
image_paths.append(x['path'])
print(image_paths)
# if not image_paths:
# raise DropItem("Item contains no files")
# item['image_paths'] = image_paths
# return item
# return [scrapy.Request(x) for x in item.get(self.images_urls_field, [])]
#
# pass
# num = 0
# def process_item(self, item, spider):
# self.num =1
# with open(str(self.num) ".jpg","wb") as f:
# f.write(item["content"])
# return item