天天看點

python_爬蟲 20 Scrapy架構之(六)下載下傳檔案和圖檔下載下傳檔案和圖檔

目錄

下載下傳檔案和圖檔

一、為什麼要選擇使用 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
           

目錄