《精通Scrapy网络爬虫》第九章

FilesPipeline和ImagesPipeline


Scrapy框架内部提供了两个Item Pipeline,专门用于下载文件和图片:

  • FilesPipeline
  • ImagesPipeline

FilesPipeline使用说明:

  • 在配置文件settings.py中启用FilesPipeline,通常将其置于其他Item Pipeline之前:
    ITEM_PIPELINES={'scrapy.pipelines.files.FilesPipeline':1}
  • 在配置文件settings.py中,使用FILES_STORE指定文件下载目录,如:
    FILES_STORE = 'download_images'
  • 在Spider解析一个包含文件下载链接的页面时,将所有需要下载文件的url地址收集到一个列表,赋给item的file_urls字段(item['file_urls'])。FilesPipeline在处理每一项item时,会读取item['file_urls'],对其中每一个url进行下载。
  • 当FilesPipeline下载完item['file_urls']中所有文件后,会将各文件的下载结果信息收集到另一个列表,赋给item的files字段(item['files'])。下载结果信息包括以下内容:
    • Path :文件下载到本地的路径(相对于FILES_STORE的相对路径)
    • Checksum:文件的校验和
    • url :文件的url地址

ImagesPipeline使用说明:

ImagesPipeline和FilesPipeline大同小异,只存在一些细微差别,如下图所示:

区别FilesPipelineImagesPipiline
导入路径scrapy.pipelines.files.FilesPipelinescrapy.pipelines.images.ImagesPipeline
Item字段file_urls,filesimage_urls,images
下载目录FILE_STOREIMAGES_STORE

ImagesPipeline特有的功能:

  • 为图片生成缩略图
    在配置文件中settings.py中设置IMAGES_THUMBS,它是一个字典,每一项的值是缩略图的尺寸:
    IMAGES_THUMBS = {
    	'small':(50,50),
    	'big':(270,270),
    }
    
    开启该功能后,下载一张图片,本地会出现三张图片。
  • 过滤掉尺寸过小的图片
    在配置文件中settings.py中设置IMAGES_MIN_WIDTHIMAGES_MIN_HEIGHT,它们分别指定图片最小的宽和高:
    IMAGES_MIN_WIDTH = 110
    IMAGES_MIN_HEIGHT = 110

下载文件


项目需求

下载http://matplotlib.org网站中所有例子的源码文件到本地

编码实现

我们按以下4步完成该项目:

  • 创建Scrapy项目,创建Spider
  • 在配置文件中启用FilePipeline,并指定文件下载目录
  • 实现ExampleItem
  • 实现ExamplesSpider
步骤1:

创建Scrapy项目,取名为matplotlib_examples,在Spider目录里创建examples.py
在这里插入图片描述

步骤2:

在配置文件中settings.py中启用FilesPipeline,并指定文件下载目录,代码如下:

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

ROBOTSTXT_OBEY = True改为False,因为这个网站现在在robot.txt,里面禁止爬虫了,所以要改成不按照那个爬取协议来,否则最后会出错。

步骤3:

实现ExampleItem,需定义file_urls和files两个字段,在images.py中完成如下代码:

class ExampleItem(scrapy.Item):
    file_urls = scrapy.Field()
    files = scrapy.Field()
步骤4:

examples.py里创建并实现ExamplesSpider:

import scrapy
from scrapy.linkextractors import LinkExtractor
from ..items import ExampleItem


class ExamplesSpider(scrapy.Spider):
    name = 'examples'
    allowed_domains = ['matplotlib.org'] #过滤爬取的域名
    start_urls = ['https://matplotlib.org/examples/index.html']
    
	#提取每个例子页面的链接
    def parse(self, response):
        le = LinkExtractor(restrict_css='div.toctree-wrapper.compound',deny='/index.html$')
        print(len(le.extract_links(response)))
        for link in le.extract_links(response):
            yield scrapy.Request(link.url,callback=self.parse_example)
            
	#获取源码文件的url,将其放入一个列表,赋给ExampleItem的file_urls字段
    def parse_example(self,response):
        href = response.css('a.reference.external::attr(href)').extract_first()
        url = response.urljoin(href)
        example = ExampleItem()
        example['file_urls'] = [url]
        return  example

运行爬虫scrapy crawl examples -o examples.json
运行结果显示下载文件的url为它的shal散列值,比如d9b551310a6668ccf43871e896f2fe6e0228567d,这种文件名很不直观,我们期望把这些例子文件按照类别下载到不同目录下,所以我们可以通过修改FilesPipeline为文件命名的规则。在pipelines.py实现MyFilesPipeline,代码如下:

from scrapy.pipelines.files import FilesPipeline
from urllib.parse import urlparse
from os.path import basename,dirname,join

class MyFilesPipeline(FilesPipeline):
    def file_path(self, request, response=None, info=None):
        path = urlparse(request.url).path
        return join(basename(dirname(path)),basename(path))

修改配置文件,使用MyFilesPipeline替代 FilesPipeline:

ITEM_PIPELINES = {
    # 'scrapy.pipelines.files.FilesPipeline':1
    'matplotlib_examples.pipelines.MyFilesPipeline':1,
}

删除之前的文件,重新运行,examples_src目录如下:

到此,文件下载的项目完成。

下载图片


项目需求

下载360图片网站http://image.so.com中艺术分类下的所有图片到本地

编码实现

首先通过在该网站页面中找到艺术分类下的jQuery发送的请求,其响应结果是一个json串。
http://image.so.com/zj?ch=art&sn=%s&listtype=new&temp=1
然后我们按以下3步完成该项目:

  • 创建Scrapy项目,创建Spider
  • 在配置文件中启用ImagesPipeline,并指定图片下载目录
  • 实现ImagesSpider
步骤1:

创建Scrapy项目,取名为so_image,在Spider目录里创建images.py

步骤2:

在配置文件settings.py中启用ImagesPipeline,并指定图片下载目录,代码如下:

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

和上个项目一样,将ROBOTSTXT_OBEY = True改为False

步骤3:

images.py里创建并实现ImagesSpider:

import scrapy
from scrapy import Request
import json


class ImageSpider(scrapy.Spider):
    BASE_URL = 'http://image.so.com/zj?ch=art&sn=%s&listtype=new&temp=1'
    start_index = 0

    #限制最大下载量,防止磁盘用量过大
    MAX_DOWNLOAD_NUM = 1000

    name = 'images'
    start_urls = [BASE_URL % 0]

    def parse(self, response):
        #使用json模块解析响应结果
        infos = json.loads(response.body.decode('utf-8'))
        #提取所有图片下载url到一个列表,赋给item的'image_urls'字段
        yield {'image_urls':[info['qhimg_url'] for info in infos['list']]}

        #如count字段大于0,并且下载数量不足 MAX_DOWNLOAD_NUM,继续下载下一页图片信息
        self.start_index += infos['count']
        if infos['count'] > 0 and self.start_index < self.MAX_DOWNLOAD_NUM:
            yield  Request(self.BASE_URL % self.start_index)

运行爬虫scrapy crawl images,然后查看图片下载目录download_images,如图所示:

到此,图片下载的项目完成。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值