Skip to content
This repository has been archived by the owner on May 6, 2021. It is now read-only.

Files

Latest commit

027097f · Jul 6, 2019

History

History
418 lines (252 loc) · 17.1 KB

34.md

File metadata and controls

418 lines (252 loc) · 17.1 KB

下载和处理文件和图像

译者:OSGeo 中国

废料可重复使用 item pipelines 用于下载附加到特定项目的文件(例如,当您抓取产品并希望在本地下载其图像时)。这些管道共享一些功能和结构(我们将它们称为媒体管道),但通常您可以使用文件管道或图像管道。

两条管道都实现了以下功能:

  • 避免重新下载最近下载的媒体
  • 指定存储媒体的位置(文件系统目录、AmazonS3存储桶、Google云存储桶)

图像管道有一些用于处理图像的额外功能:

  • 将所有下载的图像转换为通用格式(JPG)和模式(RGB)
  • 缩略图生成
  • 检查图像的宽度/高度以确保它们满足最小限制

这些管道还保留当前正在计划下载的媒体URL的内部队列,并将到达的包含相同媒体的响应连接到该队列。这样可以避免在多个项目共享同一媒体时多次下载同一媒体。

使用文件管道

使用时的典型工作流 FilesPipeline 像这样:

  1. 在spider中,您抓取一个项目并将所需的URL放入 file_urls 字段。
  2. 该项从spider返回并转到项管道。
  3. 当项目到达 FilesPipeline ,中的URL file_urls 使用标准的Scrapy计划程序和下载程序(这意味着计划程序和下载程序中间软件被重用)来计划下载字段,但具有更高的优先级,在其他页面被抓取之前对其进行处理。该项在特定管道阶段保持“锁定”,直到文件完成下载(或由于某种原因失败)。
  4. 下载文件时,另一个字段( files )将用结果填充。此字段将包含一个包含有关下载文件的信息的dict列表,例如下载路径、原始的scraped url(取自 file_urls 字段)和文件校验和。列表中的文件 files 字段将保留与原始字段相同的顺序 file_urls 字段。如果某些文件下载失败,将记录一个错误,并且该文件不会出现在 files 字段。

使用图像管道

使用 ImagesPipeline 很像使用 FilesPipeline ,但使用的默认字段名不同:您使用 image_urls 对于项目的图像URL,它将填充 images 有关下载图像的信息字段。

使用 ImagesPipeline 对于图像文件,您可以配置一些额外的功能,如生成缩略图和根据图像大小过滤图像。

图像管道使用 Pillow 对于缩略图和将图像规范化为jpeg/rgb格式,因此需要安装此库才能使用它。 Python Imaging Library (PIL)在大多数情况下也应该有效,但它在某些设置中会引起问题,因此我们建议使用 Pillow 而不是皮尔。

启用媒体管道

要启用媒体管道,必须首先将其添加到项目中 ITEM_PIPELINES 设置。

对于图像管道,请使用:

ITEM_PIPELINES = {'scrapy.pipelines.images.ImagesPipeline': 1}

对于文件管道,请使用:

ITEM_PIPELINES = {'scrapy.pipelines.files.FilesPipeline': 1}

注解

您还可以同时使用文件和图像管道。

然后,将目标存储设置配置为用于存储下载的图像的有效值。否则,管道将保持禁用状态,即使将其包含在 ITEM_PIPELINES 设置。

对于文件管道,设置 FILES_STORE 设置:

FILES_STORE = '/path/to/valid/dir'

对于图像管道,设置 IMAGES_STORE 设置:

IMAGES_STORE = '/path/to/valid/dir'

支持的存储

文件系统目前是唯一官方支持的存储,但也支持将文件存储在 Amazon S3Google Cloud Storage .

文件系统存储

文件使用 SHA1 hash 文件名的URL。

例如,以下图像URL::

http://www.example.com/image.jpg

谁的 SHA1 hash 是::

3afec3b4765f8f0a07b78f98c07b83f013567a0a

将下载并存储在以下文件中::

<IMAGES_STORE>/full/3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg

在哪里?

  • &lt;IMAGES_STORE&gt; 目录是否在中定义? IMAGES_STORE 图像管道的设置。
  • full 是一个子目录,用于从缩略图中分离完整图像(如果使用)。有关详细信息,请参阅 图像的缩略图生成 .

Amazon S3存储

FILES_STOREIMAGES_STORE 可以表示AmazonS3存储桶。Scrapy会自动将文件上传到bucket。

例如,这是一个有效的 IMAGES_STORE 价值:

IMAGES_STORE = 's3://buckimg'

您可以修改用于存储文件的访问控制列表(ACL)策略,该策略由 FILES_STORE_S3_ACLIMAGES_STORE_S3_ACL 设置。默认情况下,acl设置为 private . 要使文件公开,请使用 public-read 政策:

IMAGES_STORE_S3_ACL = 'public-read'

有关详细信息,请参阅 canned ACLs 在AmazonS3开发者指南中。

因为下流的东西 boto / botocore 在内部,您还可以使用其他S3,如存储。像自我托管这样的存储 Minios3.scality . 您所需要做的就是在Scrapy设置中设置端点选项:

AWS_ENDPOINT_URL = 'http://minio.example.com:9000'

对于自托管,您可能觉得不需要使用SSL,也不需要验证SSL连接::

AWS_USE_SSL = False # or True (None by default)
AWS_VERIFY = False # or True (None by default)

谷歌云存储

FILES_STOREIMAGES_STORE 可以表示一个谷歌云存储桶。Scrapy会自动将文件上传到bucket。(需要 google-cloud-storage

例如,这些是有效的 IMAGES_STOREGCS_PROJECT_ID 设置::

IMAGES_STORE = 'gs://buckimg/'
GCS_PROJECT_ID = 'project_id'

有关身份验证的信息,请参见 documentation .

您可以修改用于存储文件的访问控制列表(ACL)策略,该策略由 FILES_STORE_GCS_ACLIMAGES_STORE_GCS_ACL 设置。默认情况下,acl设置为 '' (空字符串)这意味着云存储将bucket的默认对象acl应用于该对象。要使文件公开,请使用 publicRead 政策:

IMAGES_STORE_GCS_ACL = 'publicRead'

有关详细信息,请参阅 Predefined ACLs 在谷歌云平台开发者指南中。

使用实例

为了首先使用媒体管道, enable it .

然后,如果spider返回带有urls键的dict( file_urlsimage_urls ,对于文件或图像管道,管道将把结果放在各自的键下。( filesimages

如果您喜欢使用 Item ,然后使用必要的字段定义自定义项,如本示例中的图像管道:

import scrapy

class MyItem(scrapy.Item):

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

如果要对URL键或结果键使用其他字段名,也可以重写它。

对于文件管道,设置 FILES_URLS_FIELD 和/或 FILES_RESULT_FIELD 设置::

FILES_URLS_FIELD = 'field_name_for_your_files_urls'
FILES_RESULT_FIELD = 'field_name_for_your_processed_files'

对于图像管道,设置 IMAGES_URLS_FIELD 和/或 IMAGES_RESULT_FIELD 设置::

IMAGES_URLS_FIELD = 'field_name_for_your_images_urls'
IMAGES_RESULT_FIELD = 'field_name_for_your_processed_images'

如果您需要更复杂的内容,并且想要覆盖自定义管道行为,请参见 扩展媒体管道 .

如果有多个图像管道继承自ImagePipeline,并且希望在不同的管道中具有不同的设置,则可以设置以管道类的大写名称开头的设置键。例如,如果您的管道名为mypipeline,并且您希望有自定义图像URL字段,那么您可以定义设置mypipeline图像URL字段,并且将使用自定义设置。

其他功能

文件过期

图像管道避免下载最近下载的文件。要调整此保留延迟,请使用 FILES_EXPIRES 设置(或) IMAGES_EXPIRES ,对于图像管道),指定延迟天数:

# 120 days of delay for files expiration
FILES_EXPIRES = 120

# 30 days of delay for images expiration
IMAGES_EXPIRES = 30

两种设置的默认值都是90天。

如果您有子类filespine的管道,并且希望对其进行不同的设置,则可以设置以大写类名开头的设置键。例如,给定名为MyPipeline的管道类,您可以设置设置键:

mypipeline_files_expires=180

管道类MyPipeline的过期时间设置为180。

图像的缩略图生成

图像管道可以自动创建下载图像的缩略图。

要使用此功能,必须设置 IMAGES_THUMBS 到一个字典,其中键是缩略图名称,值是它们的尺寸。

例如::

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

使用此功能时,图像管道将使用以下格式创建每个指定大小的缩略图:

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

在哪里?

  • &lt;size_name&gt; 是在 IMAGES_THUMBS 字典键( smallbig 等)
  • &lt;image_id&gt;SHA1 hash 图像URL的

存储图像文件的示例 smallbig 缩略图名称:

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

第一个是从网站下载的完整图像。

过滤掉小图像

使用图像管道时,可以删除过小的图像,方法是在 IMAGES_MIN_HEIGHTIMAGES_MIN_WIDTH 设置。

例如::

IMAGES_MIN_HEIGHT = 110
IMAGES_MIN_WIDTH = 110

注解

大小约束根本不影响缩略图的生成。

可以只设置一个大小约束或同时设置两个大小约束。当同时设置这两种尺寸时,将只保存满足这两种最小尺寸的图像。对于上面的示例,大小为(105 x 105)或(105 x 200)或(200 x 105)的图像都将被删除,因为至少有一个维度比约束短。

默认情况下,没有大小约束,因此所有图像都会被处理。

允许重定向

默认情况下,媒体管道忽略重定向,即HTTP重定向到媒体文件URL请求将意味着媒体下载失败。

要处理媒体重定向,请将此设置设置为 True ::

MEDIA_ALLOW_REDIRECTS = True

扩展媒体管道

请参见以下自定义文件管道中可以重写的方法:

class scrapy.pipelines.files.FilesPipeline
get_media_requests(item, info)

如工作流上所示,管道将从项目中获取要下载的图像的URL。为此,可以重写 get_media_requests() 方法并返回每个文件的请求URL::

def get_media_requests(self, item, info):
    for file_url in item['file_urls']:
        yield scrapy.Request(file_url)

这些请求将由管道处理,下载完成后,结果将发送到 item_completed() 方法,作为2元素元组的列表。每个元组将包含 (success, file_info_or_error) 在哪里?

  • success 是一个布尔值,它是 True 如果图像下载成功或 False 如果因为某种原因失败了
  • file_info_or_error 是包含以下键的dict(如果成功是 True 或A Twisted Failure 如果有问题的话。
    • url -从中下载文件的URL。这是从 get_media_requests() 方法。
    • path -路径(相对于 FILES_STORE )文件的存储位置
    • checksum -A MD5 hash 图像内容的

接收的元组列表 item_completed() 保证保留从 get_media_requests() 方法。

以下是 results 论点:

[(True,
  {'checksum': '2b00042f7481c7b056c4b410d28f33cf',
   'path': 'full/0a79c461a4062ac383dc4fade7bc09f1384a3910.jpg',
   'url': 'http://www.example.com/files/product1.pdf'}),
 (False,
  Failure(...))]

默认情况下 get_media_requests() 方法返回 None 这意味着该项目没有可下载的文件。

item_completed(results, item, info)

这个 FilesPipeline.item_completed() 当单个项的所有文件请求都已完成时调用的方法(要么已完成下载,要么由于某种原因失败)。

这个 item_completed() 方法必须返回将发送到后续项管道阶段的输出,因此必须返回(或删除)该项,就像在任何管道中一样。

下面是一个 item_completed() 方法,将下载的文件路径(传入结果)存储在 file_paths 项目字段,如果该项目不包含任何文件,则将其删除::

from scrapy.exceptions import DropItem

def item_completed(self, results, item, info):
    file_paths = [x['path'] for ok, x in results if ok]
    if not file_paths:
        raise DropItem("Item contains no files")
    item['file_paths'] = file_paths
    return item

默认情况下, item_completed() 方法返回项。

请参见以下自定义图像管道中可以覆盖的方法:

class scrapy.pipelines.images.ImagesPipeline

这个 ImagesPipelineFilesPipeline ,自定义字段名并为图像添加自定义行为。

get_media_requests(item, info)

工作方式与 FilesPipeline.get_media_requests() 方法,但对图像URL使用不同的字段名。

必须返回每个图像URL的请求。

item_completed(results, item, info)

这个 ImagesPipeline.item_completed() 当一个项目的所有图像请求都已完成时(要么已完成下载,要么由于某种原因失败),将调用方法。

工作方式与 FilesPipeline.item_completed() 方法,但使用不同的字段名存储图像下载结果。

默认情况下, item_completed() 方法返回项。

自定义图像管道示例

下面是一个完整的图像管道示例,其方法如上所示:

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

class MyImagesPipeline(ImagesPipeline):

    def get_media_requests(self, item, info):
        for image_url in item['image_urls']:
            yield scrapy.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("Item contains no images")
        item['image_paths'] = image_paths
        return item