目录

下载文件和图片

一、为什么要选择使用 scrapy 内置的下载文件的方法:

二、下载文件的 Files Pipelines

三、下载图片的 Images Pipeline:

四、汽车之家 CRV 图片下载实战

setting.py

items.py

pipelines.py

crv_spider.py


 

下载文件和图片

    Scrapy 为下载 item 中包含的文件(比如在爬取到产品时,同时也想保存对应的图片)提供了一个可重用的 item pipelines。这写 pipeline 有些共同的地方和结构(我们称之为 media pipeline)。一般来说你会使用 Files Pipelines  或是 Images Pipelines。

 

一、为什么要选择使用 scrapy 内置的下载文件的方法:

    1、避免重新下载最近已经下载过的文件。
    2、可以方便的指定文件存储的路径。
    3、可以将下载的图片转换成通用的格式。比如 png, jpg
    4、可以方便的生成缩略图
    5、可以方便的检测图片的宽和高,确保他们满足最小的限制。
    6、异步下载,效率非常高。
    

二、下载文件的 Files Pipelines

    当使用 Files Pipeliens 下载文件的时候,按照以下步骤来完成:
    1、定义好一个 Item, 然后在这个 item 中定义两个属性,分别为 file_urls 以及 files, file_urls 是用来存储需要下载的图片的 url 链接,需要给一个列表。
    2、当文件下载完成后,会把文件下载的相关信息存储到 item 的 files 属性中。比如下载路径, 下载的url和文件的校验码等。
    3、在配置文件 setting.py 中配置 FILES_STORE ,这个配置是用来设置文件下载下来的路径。
    4、启动 pipeline: 在文件 setting.py 中的 ITEM_PIPELINES 设置 scrapy.pipeline.files.FilesPipeline:1 。

 

三、下载图片的 Images Pipeline:

    当使用 Images Pipeline 下载文件的时候,按照以下步骤来完成:
    1、定义好一个 Item, 然后在这个 item 中定义两个属性,分别为 image_urls 以及 images 。image_urls 是用来存储需要下载的图片的url链接,需要给一个列表。
    2、当文件下载完成后,会把文件下载的相关信息存储到 item 的 images 属性中。比如下载路径、下载的 url 和图片的校验等。
    3、在配置文件 setting.py 中配置 IMAGES_STORE, 这个配置是用来设置图片下载下来的路径。
    4、启动 pipeline : 在文件 setting.py 中的 ITEM_PIPELINES 设置 scrapy.pipeline.images.ImagesPipeline:1

 

四、汽车之家 CRV 图片下载实战

 通过 重写 ImagesPipeline 下载 CRV 这个款车的各类图片,代码如下:

setting.py

import os

BOT_NAME = 'crv'

SPIDER_MODULES = ['crv.spiders']
NEWSPIDER_MODULE = 'crv.spiders'

ROBOTSTXT_OBEY = False

DOWNLOAD_DELAY = 1

DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36',
}

ITEM_PIPELINES = {
    'crv.pipelines.CrvImagesPipeline': 1,
}

IMAGES_STORE = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "images")

items.py

import scrapy

class CrvItem(scrapy.Item):
    title = scrapy.Field()
    image_urls = scrapy.Field()
    images = scrapy.Field()

pipelines.py

import os
from crv import settings
from urllib import request
from scrapy.pipelines.images import ImagesPipeline


class CrvImagesPipeline(ImagesPipeline):

    def file_path(self, request, response=None, info=None, *, item=None):
        # 这个方法是在图片将要被存储的时候调用,来获取这个图片的存储路径。
        category = item["title"]
        category_path = os.path.join(settings.IMAGES_STORE, category)
        image_name = request.url.split("_")[-1]
        image_path = os.path.join(category_path, image_name)
        print("image_path ; {}".format(image_path))
        return image_path

crv_spider.py

import scrapy
from crv.items import CrvItem

class CrvSpiderSpider(scrapy.Spider):
    name = 'crv_spider'
    allowed_domains = ['car.autohome.com.cn']
    start_urls = ['https://car.autohome.com.cn/pic/series-s46246/314.html#pvareaid=3454542']

    def parse(self, response):
        divs = response.xpath("//div[@class='column grid-16']/div")[2:]  # 过滤掉1,2 行
        for div in divs:
            print(div.xpath(".//div[@class='uibox-title']"))
            title = div.xpath(".//div[@class='uibox-title']/a/text()").get()
            urls = div.xpath(".//ul/li/a/img/@src").getall()
            urls = list(map(response.urljoin, urls))
            item = CrvItem(title=title, image_urls=urls)
            print(item)
            yield item