十八scrapy内置媒体(图片和文件)下载方式

Posted nuochengze

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了十八scrapy内置媒体(图片和文件)下载方式相关的知识,希望对你有一定的参考价值。

scrapy为下载的item中包含的文件提供了一个可重用的item pipeline(scrapy.pipelines.media.MediaPipeline),这些Pipeline有些共同的方法和结构。

MediaPipeline共同实现了以下特性:

  (1)避免重新下载最近已经下载过的数据

  (2)指定存储的位置和方式

ImagesPipeline还提供了额外的特性:

  (1)将所有下载的图片转换成通用的格式(JPG)和模式(RGB)

  (2)缩略图生成

  (3)检查图像的宽/高,确保它们满足最小限制

MediaPipeline去重的方式:

  (1)MediaPipeline会为当前安排好的要下载的图片保留一个内部队列,并将那些到达的包含相同图片的项目连接到该队列中,避免多次下载几个item共享的同一图片

 

1、使用FilesPipeline的工作流程

  1、在一个爬虫里,抓取一个item,把其中文件的url放入file_urls组内

  2、Item从爬虫内返回,进入item pipeline

  3、当item进入filespipeline,file_urls组内的url将被Scrapy的调度器和下载器安排下载。Item会在这个特定的管道阶段保持"Locker"的状态,直到完成文件的下载(或者未完成下载而失败)

  4、当文件下载完成后,另一个字段(files)将被更新到结构中。这个组将包含一个字典列表,其中包括下载文件的信息,如下载路径、源抓取地址和文件的校验码(checksum)。files列表文件顺序将和源file_urls组保持一致。当某个文件下载失败,将会记录下错误信息,文件将不会出现在files组内。

2、使用FilesPipeline

  1、在settings.py文件的ITEM_PIPELINES中添加一条“scrapy.pipelines.files.FilesPipeline”:1

  2、在item中添加两个字段:

    (1)file_urls = scrapy.Field()

    (2)files = scrapy.Field()

  3、在settings.py文件中添加:

    (1)FILES_STORE = "./files"  # 下载路径

    (2)FILES_FILES_FIELD = ‘file_urls‘  # 文件url所在的item字段

    (3)FILES_RESULT_FIELD = "files"  # 文件结果信息所在的item字段

  4、在settings.py中的可选设置

    (1)FILES_EXPIRES = 30   # 30天过期  

    (2)IMAGES_THUMBS  = {

        "small":(50,70),

        "big":(270,270),

      }

      IMAGES_THUMBS能制作缩略图,并设置缩略图尺寸大小。

      IMAGES_EXPIRES = 30   设置文件过期时间

      IMAGES_MIN_HEIGHT和IMAGES_MIN_WIDTH来设置图片的最小高和宽

3、示例

  1、目录结构

    技术图片

 

 

     图片名称是图片下载链接由scrapy自行按经过SHA1哈希后的值

    技术图片

 

 

     image_urls存在目标url,images存放返回结果

  2、items.py代码

import scrapy


class TiantangtupianItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    href = scrapy.Field()
    image_urls = scrapy.Field()
    images = scrapy.Field()

  3、settings.py代码

BOT_NAME = tiantangtupian

SPIDER_MODULES = [tiantangtupian.spiders]
NEWSPIDER_MODULE = tiantangtupian.spiders

LOG_LEVEL = "WARNING"


# Obey robots.txt rules
ROBOTSTXT_OBEY = False


# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
    tiantangtupian.pipelines.TiantangtupianPipeline: 300,
    scrapy.pipelines.images.ImagesPipeline:1,
}
IMAGES_STORE = ./Images
IMAGES_URLS_FIELD = image_urls
IMAGES_RESULT_FIELD = images

  4、pipelines.py

class TiantangtupianPipeline:
    def process_item(self, item, spider):
        print(item)
        return item

  5、main.py  

class TttpSpider(scrapy.Spider):
    name = tttp
    allowed_domains = [ivsky.com]
    start_urls = [https://www.ivsky.com/tupian/ziranfengguang/index_1.html]

    def parse(self, response):
        li_list = response.xpath(//ul[@class="ali"]/li)
        for li in li_list:
            item = TiantangtupianItem()
            href = li.xpath(.//img/@src).extract()
            item[href] = parse.urljoin(base=response.url,url=href[0] if href else None)
            item[image_urls] = [parse.urljoin(base=response.url,url=href[0] if href else None)]
            yield item

4、定制自己的FilesPipeline

  需要继承FilesPipeline或者ImagesPipeline,重写get_media_requests和item_completed()方法。

  1、get_media_requests(item,info)方法

    需要重写get_media_requests()方法,并对各个图片url返回一个Request

    ```

    def get_media_requests(self,item,info):

      for image_url in item[‘image_urls‘]:

        yield scrapy.Request(image_url)

    ```

    当这些请求由管道处理完成后,结果results将以2-元素的元组列表形式传送到item_completed()方法中

    技术图片

 

     success是一个布尔值,当图片成功下载时为True,失败时为False

    url是图片下载的url

    path是图片存储的路径

    checksum是图片内容MD5 hash

 

  2、item_completed(results,items,info)方法

    当一个单独项目中的所有图片请求完成时,ImagesPipeline.item_completed()方法将被调用。

    results参数是get_media_requests下载完成之后返回的结果。

    item_completed()方法需要返回一个输出(可以按需要返回或丢弃项目),该item将被送到随后的ItemPipelines。

    ```

    from scrapy.exceptions import DropItem

    def item_completed(self,results,item,info):

      image_paths = [x[‘path‘] for ok,x in results if ok]  # 遍历取url

      if not image_paths:

        raise DropItem("Item contains no images")

      item[‘image_urls‘] = image_paths  #去掉没有完成下载的图片链接

      return item

    ```

  3、示例

    注意:重写的itempipeline需要在settings中注册才能使用。

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

class TiantangtupianPipeline:
    def process_item(self, item, spider):
        print(item)
        return item


class MyImagesPipeline(ImagesPipeline):
    def get_media_requests(self,item,info):
        for image_url in item[image_urls]:
            yield scrapy.Request(url=image_url)

    def item_completed(self, results, item, info):
        print("*"*50)
        pprint(results)
        print("*" * 50)
        print("-"*20)
        image_path = [x[path] for ok,x in results if ok]
        if not image_path:
            raise DropItem("Item contains no images")
        item[image_urls] = image_path
        return item

 

  

以上是关于十八scrapy内置媒体(图片和文件)下载方式的主要内容,如果未能解决你的问题,请参考以下文章

爬虫学习笔记—— Scrapy框架:媒体管道

下载文件和图片

Scrapy爬取美女图片续集 (原创)

41.配置完善爬虫代码文件及图片下载文件重命名问题-2

Python3爬虫(十八) Scrapy框架

scrapy爬取图片