Scrapy框架之利用ImagesPipeline下载图片

栏目: 编程工具 · 发布时间: 7年前

内容简介:Scrapy框架之利用ImagesPipeline下载图片

1.ImagesPipeline简介

Scrapy用ImagesPipeline类提供一种方便的方式来下载和存储图片。

特点:

  • 将下载图片转换成通用的JPG和RGB格式
  • 避免重复下载
  • 缩略图生成
  • 图片大小过滤

2.ImagesPipeline工作流程

当使用图片管道 ImagePipeline,典型的工作流程如下:

  • 在一个爬虫里,你抓取一个项目,把其中图片的URL放入image_urls组内。
  • 项目从爬虫内返回,进入项目管道。
  • 当项目进入ImagePipeline, image_urls组内的URLs将被Scrapy的调度器和下载器安排下载(这意味着调度器和中间件可以复用),当优先级更高,会在其他页面被抓取前处理. 项目会在这个特定的管道阶段保持"locker"的状态,直到完成图片的下载(或者由于某些原因未完成下载)。
  • 当图片下载完, 另一个组(images)将被更新到结构中,这个组将包含一个字典列表,其中包括下载图片的信息,比如下载路径,源抓取地址(从image_urls组获得)和图片的校验码. images列表中的图片顺序将和源image_urls组保持一致.如果某个图片下载失败,将会记录下错误信息,图片也不会出现在images组中。

3.操作过程

项目目录结构:

Scrapy框架之利用ImagesPipeline下载图片
这里写图片描述

要想成功爬取图片,需要经过以下几个步骤:

(1) 在items.py中添加image_urls、images和image_paths字段,代码如下:

class DoubanImgsItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    image_urls = Field()
    images = Field()
    image_paths = Field()

(2)在settings.py中设置条件和属性,代码如下:

# Configure item pipelines
# See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html

# ImagePipeline的自定义实现类
ITEM_PIPELINES = {
    'douban_imgs.pipelines.DoubanImgDownloadPipeline': 300,
}
#设置图片下载路径
IMAGES_STORE = 'D:\\doubanimgs'
# 过期天数
IMAGES_EXPIRES = 90  #90天内抓取的都不会被重抓

(3)在spiders/download_douban.py中书写ImageSpider的代码:

# coding=utf-8
from scrapy.spiders import Spider
import re
from scrapy import Request
from ..items import DoubanImgsItem


class download_douban(Spider):
    name = 'download_douban'

    default_headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, sdch, br',
        'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6',
        'Cache-Control': 'max-age=0',
        'Connection': 'keep-alive',
        'Host': 'www.douban.com',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
    }

    def __init__(self, url='1638835355', *args, **kwargs):
        self.allowed_domains = ['douban.com']
        self.start_urls = [
            'http://www.douban.com/photos/album/%s/' % (url)]
        self.url = url
        # call the father base function

        # super(download_douban, self).__init__(*args, **kwargs)

    def start_requests(self):

        for url in self.start_urls:
            yield Request(url=url, headers=self.default_headers, callback=self.parse)

    def parse(self, response):
        list_imgs = response.xpath('//div[@class="photolst clearfix"]//img/@src').extract()
        if list_imgs:
            item = DoubanImgsItem()
            item['image_urls'] = list_imgs
            yield item

(4)在pipelines.py中自定义ImagePipeline代码:

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy import Request
from scrapy import log


class DoubanImgsPipeline(object):
    def process_item(self, item, spider):
        return item


class DoubanImgDownloadPipeline(ImagesPipeline):
    default_headers = {
        'accept': 'image/webp,image/*,*/*;q=0.8',
        'accept-encoding': 'gzip, deflate, sdch, br',
        'accept-language': 'zh-CN,zh;q=0.8,en;q=0.6',
        'cookie': 'bid=yQdC/AzTaCw',
        'referer': 'https://www.douban.com/photos/photo/2370443040/',
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
    }

    def get_media_requests(self, item, info):
        for image_url in item['image_urls']:
            self.default_headers['referer'] = image_url
            yield Request(image_url, headers=self.default_headers)

    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

在自定义ImagePipeline代码中,作为重要的是要重载 get_media_requests(self, item, info)item_completed(self, results, item, info) 这两个函数。

  • get_media_requests(self,item, info):

ImagePipeline根据image_urls中指定的url进行爬取,可以通过get_media_requests为每个url生成一个Request。如:

for image_url in item['image_urls']:
            self.default_headers['referer'] = image_url
            yield Request(image_url, headers=self.default_headers)
  • item_completed(self, results, item, info):

图片下载完毕后,处理结果会以二元组的方式返回给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

4.爬取结果

运行结果如下:

Scrapy框架之利用ImagesPipeline下载图片
这里写图片描述

下载成功以后,你就会在刚才设置的保存图片的路径里看到下载完成的图片:IMAGES_STORE = 'D:\doubanimgs'

Scrapy框架之利用ImagesPipeline下载图片
这里写图片描述

5.扩展

默认情况下,使用ImagePipeline组件下载图片的时候,图片名称是以图片URL的SHA1值进行保存的。

如:

图片URL: http://www.example.com/image.jpg

SHA1结果:3afec3b4765f8f0a07b78f98c07b83f013567a0a

则图片名称:3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg

如果想进行更改,请参考: 使用scrapy框架的ImagesPipeline下载图片如何保持原文件名呢?


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming Python

Programming Python

Mark Lutz / O'Reilly Media / 2006-8-30 / USD 59.99

Already the industry standard for Python users, "Programming Python" from O'Reilly just got even better. This third edition has been updated to reflect current best practices and the abundance of chan......一起来看看 《Programming Python》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具