Scrapy框架之利用ImagesPipeline下载图片

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

内容简介: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下载图片如何保持原文件名呢?


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

查看所有标签

猜你喜欢:

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

创客

创客

克里斯·安德森 / 萧潇 / 中信出版社 / 2012-12 / 45.00元

★《长尾理论》、《免费》作者克里斯•安德森最新作品 ★ 创客运动,一场即将到来的革命 ★ 编辑推荐: 这是一场即将到来的革命。 这是一个创客的时代,他们引领科技行业走进了一个新的方向,即个体制造时代的到来。运用互联网和最新的工业技术进行创造,创客运动发出了最强音。 如果说《第三次工业革命》一书的核心是互联网与新能源融合在一起所引发的工业变革。那么《创客》一书的核心则是......一起来看看 《创客》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具