如何使用 Scrapy 爬取网页中的图片和文件?

2023-04-17 00:00:00 文件 网页 如何使用

使用 Scrapy 爬取网页中的图片和文件需要通过 Pipeline 中的图片和文件下载器实现。

首先,在 Scrapy 项目中的 settings.py 文件中添加以下代码来启用图片和文件下载器:

ITEM_PIPELINES = {
    'scrapy.pipelines.images.ImagesPipeline': 1,
    'scrapy.pipelines.files.FilesPipeline': 2
}

IMAGES_STORE = 'images'
FILES_STORE = 'files'

上述代码中,ITEM_PIPELINES 是下载器的管道,在其中添加了图片下载器和文件下载器。由于图片下载器需要先进行图片处理,故将其放在第一位。IMAGES_STORE 和 FILES_STORE 是图片和文件本地存储的目录。

接下来,在 Spider 中返回一个包含了图片和文件链接的 Item,然后在 Item 中添加 Field 存储链接:

import scrapy

class MyItem(scrapy.Item):
    image_urls = scrapy.Field()
    file_urls = scrapy.Field()

在 Spider 中通过 parse 方法获取到图片和文件链接并存入 Item:

import scrapy
from myproject.items import MyItem

class MySpider(scrapy.Spider):
    name = 'myspider'
    start_urls = ['http://pidancode.com']

    def parse(self, response):
        item = MyItem()
        item['image_urls'] = response.css('img::attr(src)').extract()
        item['file_urls'] = response.css('a[href$=".pdf"]::attr(href)').extract()
        yield item

上述代码中,image_urls 存储的是网页中所有 img 标签的 src 属性,file_urls 存储的是所有链接以 .pdf 结尾的 a 标签的 href 属性。

最后,在 Pipeline 中实现图片和文件的下载:

import scrapy
from scrapy.pipelines.images import ImagesPipeline
from scrapy.pipelines.files import FilesPipeline
from urllib.parse import urlparse
import os

class MyProjectPipeline(ImagesPipeline, FilesPipeline):
    def file_path(self, request, response=None, info=None):
        return urlparse(request.url).path.split('/')[-1]

    def get_media_requests(self, item, info):
        for url in item.get('image_urls', []):
            yield scrapy.Request(url, meta={'type': 'image'})

        for url in item.get('file_urls', []):
            yield scrapy.Request(url, meta={'type': 'file'})

    def item_completed(self, results, item, info):
        for success, data in results:
            if success and data['type'] == 'image':
                image_path = data['path']
                if 'images' in image_path:
                    item['image'] = image_path
            elif success and data['type'] == 'file':
                file_path = data['path']
                if 'files' in file_path:
                    item['file'] = file_path
        return item

上述代码中,继承了 ImagesPipeline 和 FilesPipeline,并分别定义了 file_path 和 get_media_requests 两个方法。其中 file_path 用于定义图片的本地存储路径,这里以文件名作为路径。get_media_requests 方法用于发起下载请求,并在 meta 中添加 type 属性,用于后续区分图片和文件。item_completed 用于将下载成功的图片和文件的本地存储路径存储在 Item 中,以便后续使用。

最后,在 Spider 中指定 Pipeline:

ITEM_PIPELINES = {
    'myproject.pipelines.MyProjectPipeline': 1
}

运行 Scrapy 程序,图片和文件会分别下载到 IMAGES_STORE 和 FILES_STORE 指定的文件夹中,并在 Item 中存储对应的本地存储路径。

相关文章