用scrapy自动爬取下载图片

2015-10-04 09:29:34

本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循署名-非商业用途-保持一致的创作共用协议

其实呢,很多时候,我们需要一个手段自动地下载页面上的图片,比如做ppt时,做其他的项目要找背景图片时,而不断的右键复制粘贴不仅麻烦,还会慢慢的让我们丧失耐心,而作为一个程序员当然要使这个过程自动化啦,以前我曾经使用python的 urllib来爬取图片,今天试了试使用 scrapy来进行爬取,那酸爽简直难以置信!!!

接下来我们便来试试吧!!

实战,用scrapy爬取铃木爱理百度贴吧图片


我们要爬取的网站是这个, http://tieba.baidu.com/p/4023230951 爱理酱的图片集

那么,如何使用scrapy来下载图片呢?毕竟图片和文字并不一样,scrapy其实给我们内置了一个 ImagePipeline 来做这个工作,但是,往往我们需要自己改写他的 ImagePipeline来达到我们的目的

和前两篇一样,先在 terminal 里面输入这个,来创建一个新的 scrapy项目:

scrapy startproject airi_pic

okay,同样的,我们得到了 items.py , pipelines.py, settings.py,spider文件夹

首先,我们还是先来编写我们的容器 items.py:

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

import scrapy


class AiriPicItem(scrapy.Item):

    airi_image_url=scrapy.Field()
    images=scrapy.Field()
  • 首先,我们需要一个记录html源码中 imgsrc 的值 airi_image_url

  • 然后,因为我们要使用 image,因为scrapy 的 ImagePipeline会自动把,下载好的图片的路径等等地传到 item[image],当然,不用也是可以的。

好,接着我们开始写爬虫,同样是要用xpath来对html文件进行搜索

我们要搜索的html:

pic

在spider文件夹中,新建一个 airi_spider.py

依据这个文件,和我们之前尝试的爬虫经验,不难写出 airi_spider.py

from scrapy.spiders import Spider
from scrapy.selector import Selector

from airi_pic.items import AiriPicItem

class AiriPicSpider(Spider):
    name="airi_pic_spider"

    start_urls=[
        'http://tieba.baidu.com/p/4023230951'
    ]

    def parse(self,response):
        sel=Selector(response)

        image_url=sel.xpath("//div[@id='post_content_75283192143']/img[@class='BDG_Image']/@src").extract()
        print 'the urls:/n'
        print image_url
        print '/n'

        item=AiriPicItem()
        item['airi_image_url']=image_url

        yield item
  • 我们下载了图片的src,并将这个路径传给pipeline来处理,

这里,我们得弄清楚,图片和文字的区别,通常,文字是出现在html文档中的,而图片往往是调用,图片保存在一个路径之下,通过诸如 nginx, apache httpd 这样的服务器代理,来把静态文件做反响代理,这样储存在服务器某个路径下的文件,便可以通过http访问的办法进行访问,所以,很明确的,我们是需要需要向我们下载下来的 airi_image_url进行访问(这个url就是储存在服务器下,反向代理暴露出来的访问地址),才能下载图片

好,知道这些之后,我们来介绍 scrapy的自带的 imagepipeline,当你的 item[image——url]传递到pipeline时,scrapy的下载器和调度器会下载你的url下的图片,同时,scrapy还会智能地储存已经下载过的图片,与下载失败的图片的路径

好,我们来续写我们的 settings.py

ITEM_PIPELINES={
    'airi_pic.pipelines.AiriPicPipeline':1
}
IMAGES_STORE='你的储存图片的地址'

IMAGES_EXPIRES = 90

请自行设置自己要保存图片的路径,其实,这里你还可以设置诸如 IMAGES_THUMBS来做缩略图大小,IMAGES_MIN_HEIGHTIMAGES_MIN_WIDTH来控制下载的图片的大小过滤,而这一切都是基于python的图片处理库 Pillow来做的。

好,我们的改写的 pipelines.py:

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

from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy import Request

class AiriPicPipeline(ImagesPipeline):
    def get_media_requests(self,item,info):
        for image_url in item['airi_image_url']:
            yield Request(image_url)
    def item_completed(self,results,item,info):
        image_paths=[x['path'] for ok,x in results if ok]
        if not image_paths:
            raise DropItem('图片未下载好 %s'%image_paths)
  • 这里,首先, ImagesPipeline 类他有一个 get_media_requests方法来进行下载的控制,所以我们为了自定义我们的爬虫,我们自己对我们保存的 item[airi_image_url]进行一个 Request,而如果在 items.py中,我们定义的容器的名字叫 image_url就不需要这样,因为 ImagePipeline他是自动搜索这个item来进行下载,好在下载完成之后,会哟一些值传递到 item_completed 方法,包括 下载是否成功( True or False) 以及下载下来保存的路径和下载的路径,这里我们改写 这个方法让他把下载失败的(Flase)的图片的路径输出出来,不过我的这个爬虫在笔者这里尝试好像是百分百下载下来了,没有错误,

最后,让我们来运行我们的爬虫:

terminal中输入:

scrapy crawl airi_pic_spider

好了,你保存的路径下就会多了一个 full 文件夹,里面就是你下载下来的图片了

pic

这样我们就可以自动地下载爱理酱的图集,然后静静的跪舔了~~

今天我的代码全部可以在这里找得到 https://github.com/salamer/image_spider

python爬虫 返回首页

Designed and built with all the love in the world by the Mr.ALJUN.

@SERVER BY NGINX AND POWER BY DIGITALOCEAN.

© COPYRIGHT BY GAGASALAMER 2015