利用scrapy提供的专门处理下载的Pipeline(文件和图片下载),此原理与抓取页面原理一样,因此下载过程支持异步和多线程,下载十分高效。
首先:定义存储文件的路径(settings中定义IMAGES_STORE变量)
如 IMAGES_STORE = './images' ,也可以用绝对路径
from scrapy.pipelines.images import ImagesPipeline
import scrapy
from scrapy.exceptions import DropItem
class ImagePipeline(ImagesPipeline):
def get_media_requests(self, item, info):#这个方法是-获取图片的链接,并且发送图片请求
yield scrapy.Request(item['url'])
def file_path(self, request, response=None, info=None):#此方法是给下载后保存文件命名,参数request是当前下载对应的Request对象
url = request.url
file_name = url.split('/')[-1]
return file_name
def item_completed(self, results, item, info):
#当单个Item完成下载时的处理办法。因为并不是每张图片都会下载成功,所以需要分析下载结果和剔除下载失败的图片。
#如果某张图片下载失败,就不需要保存此item到数据库。
#参数results就是该Item对应的下载结果,它是一个列表形式,列表每一个元素是一个元组,其中包含下载成功或失败的信息。
#在这里,我们遍历下载结果找出所有成功的下载列表,如果列表为空,该item对应的图片下载失败,跑出DropItem异常,该Item忽略,否则返回Item
image_paths = [x["path"] for ok, x in results if ok]
if not image_paths:
raise DropItem('Image Downloaded Failed')
return item