使用scrapy图片管道下载图片

版权声明:转载请注明出处。 https://blog.csdn.net/u010358677/article/details/54090436

前言

Scrapy是Python语言下一个十分流行的爬虫框架,本文不对Scrapy本身做详细介绍。有关Scrapy的安装可以参考官网的安装指南,不过本人更推荐使用Anaconda,Anaconda集成了Python和一系列常用的的Python库,当然也包括Scrapy。安装好Anaconda,基本上就可以直接使用Scrapy了,免去了一些麻烦的依赖的安装。不过事情并非总是一帆风顺,我们依然有可能遇到一些错误。本人首次使用Scrapy的时候,在操作无误的情况下还是遇到了一个和dll文件相关的错误,问题倒不大,直接把具体的错误信息往google上一粘,很快就找到了解决办法。用google!用google!用google!重要的事情说三遍。

Scrapy是一个通用的爬虫框架,可以爬取多种形式的数据,不限于本文所讲的图片下载。关于Scrapy的工作流程、基本概念和简单例子可以参考官网的入门教程。对于网页上图片的爬取来说,Scrapy专门提供了一个item pipeline,叫做图片管道。有关图片管道的使用,官网上在下载项目图片部分里也有所介绍,而本文旨在结合一个具体的例子更清晰地说明如何使用Scrapy的图片管道爬取一个网页上的图片。

大概流程

使用Scrapy爬数据的流程大概包括如下4步:

  1. 创建一个scrapy项目。
  2. 定义要提取的Item。
  3. 编写爬取网站的爬虫(spider)。
  4. 编写Item pipeline来处理提取到的Item。

下面,我将详细介绍如何通过以上4步来完成对图片的爬取。

创建Scrapy项目

本人是在Windows7环境下进行的一系列操作,使用Anaconda自带的Scrapy,而且安装Anaconda时也允许其将相关路径加到了环境变量里,对于其他情况本人并未遇到过,这里也不做进一步的探讨。先提一点题外话,打开cmd,输入scrapy version命令可以查看当前使用的scrapy的版本情况,注意是version而不是常见的–version,截图如下:
这里写图片描述

使用Scrapy创建一个项目是要从命令行敲命令完成的,可以打开cmd,再cd到一个我们指定的路径下,也可以直接在一个指定的空文件夹上按住shift键再右击鼠标,然后在右键菜单里选择“在此处打开命令行窗口”。无论怎样,到了指定路径后,键入命令scrapy startproject image(其中,image是我们项目的名称),回车就可以创建项目了,如果成功的话,会出现大概如下图所示情况:
这里写图片描述

然后到之前指定的文件夹(test)下,会发现多了一个image文件夹,这就是刚刚创建出来的。点进image文件夹,会发现一个scrapy.cfg文件(项目配置文件,基本上不用管)和另一个image文件夹:
这里写图片描述

再点进去,又会发现一些Python文件和一个spiders文件夹,这些是我们需要修改来完成爬取任务的主要文件:
这里写图片描述

定义Item

接下来就是要定义Item,也就是要爬取的目标。从上图可以看到,items.py文件在创建项目时已经生成好了,但是里面并没有实质性的内容,我们需要对它进行修改,代码如下:

import scrapy


class ImageItem(scrapy.Item):
    image_urls = scrapy.Field()
    images = scrapy.Field()
    image_paths = scrapy.Field()

因为我们要爬取图片,所以在ImageItem类里定义了图片的url(image_urls)、图片的实际内容(images)以及图片的保存路径(image_paths)。如果除图片本身外还需要一些其他的信息,比如对图片的描述,只要是要爬取的网页中有相关内容,这里就可以进行定义,而实际的爬数据的代码要在spider类里编写。在Scrapy中,一个Item的所有成员变量都是用scrapy.Field()来初始化的。

编写爬虫

之前提到的目录结构中,有一个spiders文件夹,这是放爬虫文件的地方,初始时,里面只有一个__init__.py文件,所以我们首先需要创建一个特定的爬虫文件。在命令行中,cd到这个文件夹下,使用scrapy gensipder myimage https://tianqi.moji.com/liveview/ 命令来创建出spider文件,其中,myimage是spider的文件名,而第二个参数是一个网址,代表allowed_domains。allowed_domains是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页。使用命令创建spider文件截图如下:
这里写图片描述

创建出的spider文件具体内容如下:

import scrapy


class MyimageSpider(scrapy.Spider):
    name = "myimage"
    allowed_domains = ["https://tianqi.moji.com/liveview/"]
    start_urls = (
        'http://www.https://tianqi.moji.com/liveview//',
    )

    def parse(self, response):
        pass

可以看到,类名以及其中的一些固定的成员变量都自动生成好了,类名和name变量(爬虫的唯一标识)都是根据命令中的文件名创建出来的,而allowed_domains和start_urls是根据第二个参数创建的。start_urls就是我们要爬取的网址,它默认是和allowed_domains一样,不过,我们这里需要对其进行一下修改,改成一个更具体的网址,而不是一个域名约束范围。
parse函数是进行网页内容爬取的主要函数,起始时它没有函数体(仅有个pass而已),针对自己的任务,我们要对这个文件做特异的编写,修改parse函数前,首先要import我们之前定义的item类,修改过的spider文件代码如下:

# -*- coding: utf-8 -*-
import scrapy
from image.items import ImageItem

class MyimageSpider(scrapy.Spider):
    name = "myimage"
    allowed_domains = ["https://tianqi.moji.com/liveview/"]
    start_urls = (
        'https://tianqi.moji.com/liveview/china/shaanxi/qujiang-ocean-world',
    )

    def parse(self, response):
        item = ImageItem()
        item['image_urls'] = response.xpath('//img[@data-original]/@data-original').extract()
        return item

注意,代码中我确实修改了start_urls(关于墨迹天气时景的一个具体网址)。在parse函数中,首先创建一个item对象,然后就是解析html网页,爬取我们想要的内容,在这里我们想要的是网页中图片的地址。Scrapy使用xpath语法来解析html,可以是说这是使用scrapy做爬虫的一个非常核心的部分,所以如果想实现自己的爬虫,还必须了解xpath,推荐学习w3school的XPath教程。另外,还要对要爬取的网页做一定的源码分析(网页中点鼠标右键,选查看网页源代码),这样才能针对要爬取的内容写出真正能起作用的xpath语句。parse函数最后我们将item对象返回即可,Scrapy框架下自会有其他函数来调用它。图片的保存路径不属于爬虫本身管辖的范围,在parse函数里不用管,而图片的实际内容也是在爬虫实际运行起来后,由Scrapy来负责的,这里也不用额外处理。

编写Item Pipeline 文件

在创建项目时,会自动生成一个pipelines.py文件,里面包含一个ItemPipeline类,这个类是用来处理爬虫爬取到的item的,比如丢掉一些错误的item等等。本文之前讲的东西其实和本文的主题并没有特别紧密的关系,前面的流程几乎适用于爬任何数据。而使用Scrapy图片管道下载图片从这里开始有点不一样了。由于Scrapy为我们提供好了一个ImagesPipeline(图片管道),所以最简单的图片下载方式可以不用对生成的pipelines.py文件做任何修改,只需配置settings.py(也是创建项目时自动生成)文件即可。settings.py文件中需加入以下信息:

ITEM_PIPELINES = {
    'scrapy.contrib.pipeline.images.ImagesPipeline': 1
}

IMAGES_STORE = 'D:\\pachong\\images\\'
IMAGES_EXPIRES = 90
IMAGES_MIN_HEIGHT = 100
IMAGES_MIN_WIDTH = 100

其中,ITEM_PIPELINES = { ‘scrapy.contrib.pipeline.images.ImagesPipeline’: 1}指定了使用Scrapy提供的ImagesPipeline来做ItemPipeline。IMAGES_EXPIRES指定的是图片的过期时间。IMAGES_STORE 指定了图片的存储路径,IMAGES_MIN_HEIGHT和IMAGES_MIN_HEIGHT分别指定图片的最小高度和最小宽度,起到一个过滤的作用。settings.py还有一个地方要改,那就是把ROBOTSTXT_OBEY由True改成False。否则,一些防爬虫爬数据的页面可能会拒绝请求,本人遇到的情况如下图所示:
这里写图片描述

Scrapy默认遵守robot协议,也就是ROBOTSTXT_OBEY的初值为True。但是遇到防爬取页面,就会碰壁。

最后就是实际运行爬虫爬数据了,在命令行中,cd到我们之前创建的项目路径下,键入scrapy crawl myimage命令,回车即可开始工作。myimage就是爬虫文件的文件名,也是文件中name变量对应的值。运行结果如下:
这里写图片描述

这里写图片描述

爬虫工作完之后,我们会在settings.py指定的存储文件夹下,看到刚下载到的图片:
这里写图片描述

总结

到此,使用Scrapy提供的图片管道下载图片的整个流程就介绍完了。如果还想对这些图片做一些额外的处理,比如规定它们的文件名,那就需要实现定制图片管道了,本文就不对这部分做介绍了,可以参考官网下载项目图片或者其他博客,比如这篇scrapy 下载图片 ImagesPipeline。记得要在settings.py文件中将ITEM_PIPELINES设为自己的ItemPipeline。

猜你喜欢

转载自blog.csdn.net/u010358677/article/details/54090436