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.操作过程

项目目录结构:

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

(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.爬取结果

运行结果如下:

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



5.扩展

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

如:
图片URL:http://www.example.com/image.jpg
SHA1结果:3afec3b4765f8f0a07b78f98c07b83f013567a0a
则图片名称:3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg

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


时间: 2024-10-04 00:01:54

Scrapy框架之利用ImagesPipeline下载图片的相关文章

利用Python的Scrapy框架十分钟爬取美女图的教程

简介 scrapy 是一个 python 下面功能丰富.使用快捷方便的爬虫框架.用 scrapy 可以快速的开发一个简单的爬虫,官方给出的一个简单例子足以证明其强大: 快速开发 下面开始10分钟倒计时: 1. 初始化项目 scrapy startproject mzt cd mzt scrapy genspider meizitu meizitu.com 2. 添加 spider 代码: 定义 scrapy.Item ,添加 image_urls 和 images ,为下载图片做准备. 修改 s

在Android远程上传以及下载图片---XFire框架

http://blog.csdn.net/haha_mingg/article/details/6347588   有时我们可以看到,图片往往被提交到服务器端,这里我通过XFire框架来实现远程上传以及下载图片的功能. 首先我们来看看从服务器端下载图片的功能:   我用的是KSOAP框架,我之前的文章有讲述过.在这里不要多说,贴上代码.   首先我们看看Acitivity中的代码:  [java] view plaincopyprint? package com.net.connect.app;

Android 利用ViewPager实现图片可以左右循环滑动效果附代码下载_Android

首先给大家展示靓照,对效果图感兴趣的朋友可以继续往下阅读哦. ViewPager这个小demo实现的是可以左右循环滑动图片,下面带索引,滑到最后一页在往右滑动就要第一页,第一页往左滑动就到最后一页,上面是效果图,用美女图片是我一贯的作风,呵呵  1.    首先看一些layout下的xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width=&qu

利用SoftReference实现图片异步加载

//以下是mars讲解的软引用 对象存在与堆中,对象的引用存在于栈中 比如: Object obj=new Object()//obj在栈中 obj=null 当堆内存中的对象没有任何引用指向时,垃圾回收机制会回收此块内存.即当obj=null时. 软引用: 可以保证垃圾回收机制,但是同时这个引用指向块堆里的内存.所以叫软引用. 调用 Object obj=sr.get()时,假若这个对象已经被回收那么get()方法将会返回null 可以采用MAP作为缓存.缓存里存放的是键值对,键是图片的url

android-安卓关于下载图片和下载文件的问题

问题描述 安卓关于下载图片和下载文件的问题 图片 安卓中下载图片有几种方法?用URL下载? 文件 文件都是从服务器中下载下来后解析吗? 解决方案 如果自己加载的话,需要自己写网络去请求url地址进行下载.类似于这样 URL url = new URL(uri); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod(""GET""); conn.

python 下载 图片、音乐、视频 和 断点续传

参考: http://www.pythontab.com/html/2014/pythonjichu_0121/681.html 参考: http://blog.csdn.net/supercooly/article/details/51046561 参考: python编写断点续传下载软件 参考: http://blog.topspeedsnail.com/archives/8462 python下载文件的三种方法 当然你也可以利用ftplib从ftp站点下载文件.此外Python还提供了另外

Android异步下载图片并且缓存图片到本地

http://lishuaishuai.iteye.com/blog/1806667 在Android开发中我们经常有这样的需求,从服务器上下载xml或者JSON类型的数据,其中包括一些图片资源,本demo模拟了这个需求,从网络上加载XML资源,其中包括图片,我们要做的解析XML里面的数据,并且把图片缓存到本地一个cache目录里面,并且用一个自定义的Adapter去填充到LIstView,demo运行效果见下图: 通过这个demo,要学会有一下几点 1.怎么解析一个XML 2.demo中用到的

android-Android中如何使用ImageLoader下载图片到SD卡

问题描述 Android中如何使用ImageLoader下载图片到SD卡 Android中可以使用ImageLoader将图片下载到手机本地的SD卡吗 有没有别的好的关于图片下载的框架 解决方案 最通用的就是Universal-Image-Loader http://blog.csdn.net/shineflowers/article/details/44650425 参考其中"加载其他来源的图片" 解决方案二: 用Universal-Image-Loader吧,方便简单效率高,配置一

iOS异步下载图片实例代码_IOS

写在前面 在iOS开发中,无论是在UITableView还是在UICollectionView中,通过网络获取图片设置到cell上是较为常见的需求.尽管有很多现存的第三方库可以将下载和缓存功能都封装好了供开发者使用,但从学习的角度出发,看懂源码,理解其中的原理,结合自身的实际需求写出自己的代码是很必要的.在刚结束的Demo中,有用到异步图片下载功能,这篇笔记就是对整个实现的简单整理. 基本思路 •cell中添加一个UIImageView •cell拥有url,发起下载请求,注册下次完成通告,在通