Scrapy设置之Downloading media

Scrapy提供了一些可重用的Item Pipeline来下载与 Item相关的文件。例如,当在抓取某个商品的信息时,可能也想把它的图片下载下来。这些Pipeline的功能和结构都有些类似(我们把它们叫做Media Pipeline),但最常用的是Images PipelineFiles Pipeline

这两种Pipeleine都有如下特点:

  • 可以避免重复下载。
  • 可以指定存储位置,如本地文件系统和Amazon S3 bucket。

Images Pipeline对于处理图片还有一些额外的功能:

  • 将所有下载下来的图片都转换成JPG格式和RGB颜色模式。
  • 可以生成缩略图。
  • 检查图片的宽度和高度,确保它们满足最小的尺寸约束条件。

这些Pipeline同时在内部维持一个正被调度以待下载的媒体url的队列,并且把包含相同媒体的响应与队列关联起来。这样可以避免当多个Item都包含同一个媒体时这个媒体不会被下载多次。

使用Files Pipeline的一般工作流程是这样的:

  1. 在一个爬虫中,抓取到一个Item,把需要下载的文件的URL放到file_urls字段中去。
  2. 这个Item从爬虫中返回,并到达Item Pipeline
  3. 当这个Item到达FilesPipeline时,file_urls字段中的url会通过标准的Scrapy调度器和下载器进行调度和下载,不过这种调度的优先级较高,会在其他页面被抓取之前就处理这些url。处理的过程中,这个Item会被这个pipeline加上锁,直到文件下载完毕或者由于某些原因下载失败。
  4. 当文件下载完毕之后,下载的结果会被填充到另外一个字段,叫做files。这个字段包含了一个字典的列表,里面是下载下来的文件的信息,例如,下载后放置的路径、是从哪个url抓取的(从file_urls字段获得此信息)以及文件检验和。files字段列表文件顺序和file_urls字段顺序是一致的。如果某个文件下载失败,那么错误记录到日志里,而文件不会出现在files字段。

ImagesPipeline的使用方法和FilesPipeline很大程度上是相同的,只是一些默认的字段名称不同:用image_urls字段存放需要下载的图片的地址,下载完毕后图片信息填充到images字段中。

使用ImagesPipeline来处理专门图片文件有一些好处是你可以额外地设置一些函数来生成缩略图或者基于图片的尺寸来对图片进行过滤。

ImagesPipeline使用Pillow库来生成缩略图以及把图片标准化为JPEG/RGB格式,在使用之前需要先安装。PIL在在多数情况下也是可以使用的,不过在某些设置中会导致一些问题。因此建议还要使用Pillow来代替。

要使用媒体管道,需要先启用它:

首先把它加到工程的ITEM_PIPELINES设置项中,对于Images Pipeline,可以这样写:

ITEM_PIPELINES = {‘scrapy.pipelines.images.ImagesPipeline’: 1}

而对于Files Pipeline,要这样写:

ITEM_PIPELINES = {‘scrapy.pipelines.files.FilesPipeline’: 1}

可以同时使用这两个Pipeline。

然后需要给下载下来的文件配置一个有效的存储位置,否则这个pipeline仍然不能使用,即使已经在ITEM_PIPELINES里添加了它。对于Files Pipeline是:

FILES_STORE = ‘/path/to/valid/dir’

对于Images Pipeline是:

IMAGES_STORE = ‘/path/to/valid/dir’

根据以上两个步骤启用了媒体管道之后,如果爬虫返回的是字典,其中有个键为file_urls或者image_urls,相应的pipeline就会以把结果分别存储在files或者images键中。

如果爬虫的输出采用的是Item,那就需要在定义的item中添加一些必要的字段,像这样:

import scrapy

class MyItem(scrapy.Item):

    # ... other item fields ...
    image_urls = scrapy.Field()
    images = scrapy.Field()

这些必要的字段的名字也可以由设置项来修改,image_urls这个字段可以由IMAGES_URLS_FIELD来设置,images这个字段可以由IMAGES_RESULT_FIELD来设置。

至于文件的存储方式,目前官方支持的只有本地文件系统这一种方法,但也同时支持在Amazon S3上存储文件。

在本地文件系统上,文件名是用相应的url的SHA1哈希得来的,比如这个图片的url是http://www.example.com/image.jpg
,哈希之后对应的结果是3afec3b4765f8f0a07b78f98c07b83f013567a0a
,它会被下载下来然后存储到:

<IMAGES_STORE>/full/3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg

其中,<IMAGES_STORE>是在启用Images Pipeline时设置的IMAGES_STORE选项代表的目录。而full是用来区分完整的图片和缩略图而产生的子目录(如果生成了缩略图的话)。

这些媒体管道不会下载最近已经下载过的文件,除非文件已经过期,而这个过期时间就是由FILES_EXPIREIMAGES_EXPIRE来设置的,单位为天。如:

# 90 days of delay for files expiration
FILES_EXPIRES = 90

# 30 days of delay for images expiration
IMAGES_EXPIRES = 30

Images Pipeline可以自动地为图片生成缩略图,如果要启用这个功能,需要把IMAGES_THUMBS设置成一个字典,其键为缩略图的,其值为相应的尺寸,例如:

IMAGES_THUMBS = {
    'small': (50, 50),
    'big': (270, 270),
}

Images Pipeline生成的缩略图存储位置的格式为:

<IMAGES_STORE>/thumbs/<size_name>/<image_id>.jpg

其中,<size_name>是在IMAGES_THUMBS字典中设置的键,比如smallbig等等。而<image_id>则是图片的url对应的哈希值。

分别以smallbig为名字生成的缩略示例如下所示:

<IMAGES_STORE>/full/63bbfea82b8880ed33cdb762aa11fab722a90a24.jpg
<IMAGES_STORE>/thumbs/small/63bbfea82b8880ed33cdb762aa11fab722a90a24.jpg
<IMAGES_STORE>/thumbs/big/63bbfea82b8880ed33cdb762aa11fab722a90a24.jpg

第一行是完整的图片,从网站上下载的原始图片。

使用Images Pipeline时,设置了IMAGES_MIN_HEIGHTIMAGES_MIN_WIDTH的值后,可以丢弃尺寸过小的图片。例如:

IMAGES_MIN_HEIGHT = 110
IMAGES_MIN_WIDTH = 110

要注意的是,这种尺寸约束不会影响缩略图的生成。默认情况下,没有图片的尺寸约束,所有的图片都会被处理。

如果还要实现更加复杂的功能,就需要自己实现Pipeline的逻辑,可以参考Scrapy文档。

你可能感兴趣的:(scrapy)