Python爬虫5.9 — scrapy框架下载文件和图片

综述

本系列文档用于对Python爬虫技术的学习进行简单的教程讲解,巩固自己技术知识的同时,万一一不小心又正好对你有用那就更好了。
Python 版本是3.7.4

本篇文章主要pipeline模块下载文件和图片的使用。

下载文件和图片

Scrapy为下载item中包含的文件(比如再爬取到产品时,同时也想保存到对应图片)提供了一个可重用的item pipeline。这些pipeline有些共同的方法和结构(我们称之为media Pipeline),一般来说我们会使用到File PipelineImages Pipeline

使用Scrapy框架内置方法的好处

我们为什么要选择用Scrapy内置的下载文件的防范:

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

下载文件的File Pipeline

当使用File Pipeline下载文件的时候,按照以下步骤来完成:

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

下载图片的Images Pipeline

当使用Images Pipeline下载文件的时候,按照以下步骤来完成:

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

实例说明

我们就以爬取汽车之家中的图片为例。

传统下载方式

传统的下载方式在这里就简单说下步骤:

  1. 使用scrapy命令创建项目;
  2. 使用命令创建爬虫;
  3. 更改setting.py文件配置信息;
  4. 编写items.py代码;
  5. 编写spider模块下代码(爬取网页中需要下载的图片链接);
  6. 编写pipelines.py代码(进行数据处理,图片的保存等)。

pipelines.py代码如下:

import os
import urllib.request


class BmwPipeline(object):

    def __init__(self):
        # 创建文件保存文件夹
        self.image_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images')
        if not os.path.exists(self.image_path):
            os.mkdir(self.image_path)

    def process_item(self, item, spider):
        category = item['category']
        img_urls = item['img_urls']
        # 创建图片类别文件夹
        category_path = os.path.join(self.image_path, category)
        if not os.path.exists(category_path):
            os.mkdir(category_path)
        
        # 根据图片url进行下载保存图片
        for url in img_urls:
            img_name = url.split('_')[-1]
            urllib.request.urlretrieve(url=url, filename=os.path.join(category_path, img_name))
            print(img_name)

        return item

通过上述代码我们就可以将爬取的图片url进行处理保存图片到本地。但是这种处理方式一个很大的缺点就是图片只能一个一个下载不能进行异步下载。下面我们使用Scrapy框架中自带的图片下载进行下载图片。

使用Scrapy框架自带ImagesPipeline进行下载图片

按照上述的步骤进行编写相应的代码:

  1. 定义好一个Item,然后再这个Item中定义两个属性,分别为image_urls以及images。编写items.py代码如下:
    import scrapy
    
    
    class BmwItem(scrapy.Item):
        category = scrapy.Field()
        image_urls = scrapy.Field()
        images = scrapy.Field()
    
  2. 在配置文件setting.py中配置IMAGES_STORE。增加代码如下:
    # 图片下载路径,供image pipeline使用
    IMAGES_STORE = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images')
    
  3. 启动pipeline:在ITEM_PIPELINES中设置scrapy.pipelines.images.ImagesPipeline:1。修改代码如下:
    ITEM_PIPELINES = {
        # 'bmw.pipelines.BmwPipeline': 300,
        'scrapy.pipelines.images.ImagesPipeline': 1
    }
    
  4. 编写spider模块代码如下:
    import scrapy
    from bmw.items import BmwItem
    
    class Bmw5Spider(scrapy.Spider):
        name = 'bmw5'
        allowed_domains = ['car.autohome.com.cn']
        start_urls = ['https://car.autohome.com.cn/pic/series/65.html']
    
        def parse(self, response):
            uiboxs = response.xpath('//div[@class="uibox"]')[1:]
    
            for uibox in uiboxs:
                category = uibox.xpath('.//div[@class="uibox-title"]/a/text()').get()
                img_urls_tmp = uibox.xpath('.//ul/li/a/img/@src').getall()
                img_urls = list(map(lambda url:response.urljoin(url),img_urls_tmp))
                item = BmwItem(category=category,image_urls=img_urls)
                yield item
    

运行代码你会发现其能很快的将图片下载完成。下载完成后你会在你定义的图片保存文件夹images下多了一个full文件夹,这个里面就是所下载下来的所有图片。有的想问如果我还想要根据分类继续保存图片需要怎么办呢?这就需要我们去重写ImagesPipeline类中的一些方法了。通过读ImagesPipeline类的代码我们可以知道,类中有两个方法分别是get_media_requestsfile_path

  • get_media_requests : 这个方法是在发送下载请求之前调用,其实这个方法本身就是去发送下载请求的。
  • file_path : 这个方式是在图片将要被存储时候调用,来获取这个图片的存储路径。

优化方案如下:

  1. pipelines.py中重写声明定义一个类,继承ImagesPipeline;
  2. 在此子类中重新这两个方法代码如下:
    import os
    import urllib.request
    
    from scrapy.pipelines.images import ImagesPipeline
    from bmw import settings
    
    
    class BmwImagesPipeline(ImagesPipeline):
    
        # 重写get_media_requests方法
        def get_media_requests(self, item, info):
            # 这个方法是在发送下载请求之前调用
            # 其实这个方法本身就是去发送下载请求的
            request_objs = super(BmwImagesPipeline, self).get_media_requests(item, info)
            # 将item数据加入到请求中
            for requests_obj in request_objs:
                requests_obj.item = item
            return request_objs
    
        # 重写file_path方法
        def file_path(self, request, response=None, info=None):
            # 这个方式是在图片将要被存储时候调用,来获取这个图片的存储路径
            # 获取父类返回的保存地址
            path = super(BmwImagesPipeline, self).file_path(request, response, info)
            
            category = request.item.get('category')
            images_store = settings.IMAGES_STORE
            # 创建图片分类文件夹
            category_path = os.path.join(images_store, category)
            if not os.path.exists(category_path):
                os.mkdir(category_path)
    
            # 重新返回新的图片保存路径
            image_name = path.replace('full/', '')
            image_path = os.path.join(category_path, image_name)
            return image_path
    
  3. 重新修改setting.py中的ITEM_PIPELINES配置如下:
    ITEM_PIPELINES = {
        # 'bmw.pipelines.BmwPipeline': 300,
        # 'scrapy.pipelines.images.ImagesPipeline': 1
        'bmw.pipelines.BmwImagesPipeline': 300,
    }
    

之后运行代码即可。

其他博文链接

  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Scrapy是一个基于Python爬虫框架,它可以帮助我们快速高效地抓取网站数据。在这里,我将介绍Scrapy的基本用法,让您能够快速入门。 安装Scrapy ----------------------- 在安装Scrapy之前,我们需要先安装Python。然后,我们可以通过以下命令来安装Scrapy: ``` pip install scrapy ``` 创建Scrapy项目 ----------------------- 创建Scrapy项目的命令是: ``` scrapy startproject project_name ``` 这个命令将会在当前目录下创建一个名为project_name的文件夹,其中包含了Scrapy项目的基本结构。 编写Spider ----------------------- 在Scrapy中,Spider是用来定义爬取网站的规则的。我们可以通过以下命令来创建一个Spider: ``` scrapy genspider spider_name domain_name ``` 其中,spider_name是我们自己定义的Spider名称,domain_name是我们要抓取的网站域名。 接下来,我们需要在Spider中定义如何爬取网站。这里我们以爬取“http://quotes.toscrape.com/”网站上的名言警句为例。我们可以在Spider中定义如下规则: ```python import scrapy class QuotesSpider(scrapy.Spider): name = "quotes" start_urls = [ 'http://quotes.toscrape.com/page/1/', 'http://quotes.toscrape.com/page/2/', ] def parse(self, response): for quote in response.css('div.quote'): yield { 'text': quote.css('span.text::text').get(), 'author': quote.css('span small::text').get(), 'tags': quote.css('div.tags a.tag::text').getall(), } next_page = response.css('li.next a::attr(href)').get() if next_page is not None: yield response.follow(next_page, self.parse) ``` 在上述代码中,我们首先定义了Spider的名称,接着定义了我们要爬取的起始URL,最后定义了如何解析网页的函数parse()。在parse()函数中,我们使用了Scrapy的选择器来提取网页中的名言警句,并将其保存到字典中。接着,我们使用response.follow()函数来获取下一页的URL,并继续解析。 运行Spider ----------------------- 要运行我们刚才创建的Spider,我们可以使用以下命令: ``` scrapy crawl spider_name ``` 其中,spider_name是我们之前创建的Spider名称。 Scrapy会自动去抓取我们定义的起始URL,并根据我们定义的规则来解析网页。解析完成后,Scrapy会将结果保存到我们指定的位置。 总结 ----------------------- Scrapy是一个非常强大的Python爬虫框架,它可以帮助我们快速高效地抓取网站数据。在本教程中,我们介绍了Scrapy项目的创建、Spider的定义以及如何运行Spider。如果您想更深入地学习Scrapy,可以参考官方文档:https://docs.scrapy.org/en/latest/。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值