scrapy的快速入门(二)

下载及处理文件和图片
Scrapy为下载item中包含的文件(比如在爬取到产品时,同时也想保存对应的图片)提供了一个可重用的 item pipelines . 这些pipeline有些共同的方法和结构(我们称之为media pipeline)。一般来说你会使用Files Pipeline或者 Images Pipeline。
这两种pipeline都实现了以下特性:
1、避免重新下载最近已经下载过的数据;
2、指定存储媒体的位置(文件系统目录,Amazon S3 bucket)图像管道有一些额外的功能来处理图像;
3、将所有下载的图片转换成通用的格式(JPG)和模式(RGB);
4、缩略图生成;
5、检测图像的宽/高,确保它们满足最小限制;

这个管道也会为那些当前安排好要下载的图片保留一个内部队列,并将那些到达的包含相同图片的项目连接到那个队列中。 这可以避免多次下载几个项目共享的同一个图片。

一、使用Files Pipeline
当使用 FilesPipeline ,典型的工作流程如下所示:
1、在一个爬虫里,你抓取一个项目,把其中图片的URL放入 file_urls 组内。
2、项目从爬虫内返回,进入项目管道。
3、当项目进入 FilesPipeline,file_urls 组内的URLs将被Scrapy的调度器和下载器(这意味着调度器和下载器的中间件可以复用)安排下载,当优先级更高,会在其他页面被抓取前处理。项目会在这个特定的管道阶段保持“locker”的状态,直到完成文件的下载(或者由于某些原因未完成下载)。
4、当文件下载完后,另一个字段(files)将被更新到结构中。这个组将包含一个字典列表,其中包括下载文件的信息,比如下载路径、源抓取地址(从 file_urls 组获得)和图片的校验码(checksum)。 files 列表中的文件顺序将和源 file_urls 组保持一致。如果某个图片下载失败,将会记录下错误信息,图片也不会出现在 files 组中。

二、使用图像管道Images Pipeline
当使用 ImagesPipeline ,典型的工作流程如下所示:
1、在一个爬虫里,你抓取一个项目,把其中图片的URL放入 image_urls 组内。
2、项目从爬虫内返回,进入项目管道。
3、当项目进入 ImagesPipeline,image_urls 组内的URLs将被Scrapy的调度器和下载器(这意味着调度器和下载器的中间件可以复用)安排下载,当优先级更高,会在其他页面被抓取前处理。项目会在这个特定的管道阶段保持“locker”的状态,直到完成文件的下载(或者由于某些原因未完成下载)。
4、当文件下载完后,另一个字段(images)将被更新到结构中。这个组将包含一个字典列表,其中包括下载文件的信息,比如下载路径、源抓取地址(从 image_urls 组获得)和图片的校验码(checksum)。 files 列表中的文件顺序将和源 image_urls 组保持一致。如果某个图片下载失败,将会记录下错误信息,图片也不会出现在 images 组中。

使用ImagesPipeline非常类似于使用FilesPipeline,除了使用的默认字段名称不同:您使用image_urls作为项目的图像URL,并将填充图像字段以获取有关下载的图像的信息。
使用ImagesPipeline进行图像文件的优点是您可以配置一些额外的功能,例如生成缩略图,并根据大小对图像进行过滤。
Pillow 是用来生成缩略图,并将图片归一化为JPEG/RGB格式,因此为了使用图片管道,你需要安装这个库。 Python Imaging Library (PIL) 在大多数情况下是有效的,但众所周知,在一些设置里会出现问题,因此我们推荐使用 Pillow 而不是PIL。

下面利用Images Pipeline爬取花瓣网下载想要的图片。

1、新建一个工程,打开cmd,
输入scrapy startproject huaban_imagepipeline

新建工程

这里的每个文件的含义上一篇文章scrapy的快速入门(一)已介绍过了,可以自行翻看之前的文章;
2、定制item

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class HuabanImagepipelineItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    image_urls = scrapy.Field()  # 图片的链接
    images = scrapy.Field()

3、爬虫的关键部分——spiders
在spiders的文件下新建一个huaban_spider.py

import scrapy
from ..items import HuabanImagepipelineItem
from scrapy.conf import settings #从settings文件中导入Cookie,这里也可以from scrapy.conf import settings.COOKIE
import requests
import json
import math
from scrapy.http import Request


class HuabanSpider(scrapy.Spider):
    name = "huabanSpider"
    allowed_domains = ['huaban.com']
    query = "张敏"
    start_urls = ['http://huaban.com/search/?q=%s' % query]
    # 带着Cookie向网页发请求
    cookie = settings['COOKIE']
    #利用抓包获取必要的参数,这里我用的是postman
    headers = {
        'cookies': 'uid=21839587; sid=8ckMdriGQD28yFUdISQIqykQwGn.KuxyNV3X2l9A87ShUPD1LLauT6PZdgi4AUm44wZqFXs;',
        'X-Requested-With': 'XMLHttpRequest',
    }

    html = requests.get(start_urls[0], headers = headers).content
    infos = json.loads(html)
    totalpage = math.ceil(int(infos['pin_count'])/20) #总的页数

    #构造每页的链接
    def parse(self, response):
        for i in range(1, int(self.totalpage) + 1):
            page = str(i)
            urls = ["http://huaban.com/search/?q={}&page={}".format(self.query, page)]
            for url in urls:
                yield Request(url, headers = self.headers, meta = {'key':url}, callback=self.parse_image)

    #构造每个图片下载的链接
    def parse_image(self, response):
        item = HuabanImagepipelineItem()
        pin_html = requests.get(response.meta['key'], headers=self.headers).content
        infos = json.loads(pin_html)
        pins = infos['pins']
        url_list = []
        for pin in pins:
            key_id = pin['file']['key']
            download_url = "http://img.hb.aicdn.com/" + key_id + "_fw658"
            url_list.append(download_url)
        item['image_urls'] = url_list
        yield item

4、图片管道pipeline

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline
import scrapy


class HuabanImagepipelinePipeline(ImagesPipeline):

    def get_media_requests(self, item, info):  # 重写ImagesPipeline   get_media_requests方法
        '''
        :param item:
        :param info:
        :return:
        在工作流程中可以看到,
        管道会得到文件的URL并从项目中下载。
        为了这么做,你需要重写 get_media_requests() 方法,
        并对各个图片URL返回一个Request:
        '''
        for image_url in item['image_urls']:
            yield scrapy.Request(image_url)

    def item_completed(self, results, item, info):
        '''
        当一个单独项目中的所有图片请求完成时(要么完成下载,要么因为某种原因下载失败),
         item_completed() 方法将被调用。
        '''
        image_paths = [x['path'] for ok, x in results if ok]
        if not image_paths:
            raise DropItem("Item contains no images")
        item['image_paths'] = image_paths
        return item

在自定义ImagePipeline代码中,作为重要的是要重载get_media_requests(self, item, info)和item_completed(self, results, item, info)这两个函数。
1)get_media_requests(self,item, info):
ImagePipeline根据image_urls中指定的url进行爬取,可以通过get_media_requests为每个url生成一个Request;比如:

    def get_media_requests(self, item, info):
        for image_url in item['image_urls']:
            yield scrapy.Request(image_url)

2)图片下载完毕后,处理结果会以二元组的方式返回给item_completed()函数。这个二元组定义如下:
(success, image_info_or_failure)
其中,第一个元素表示图片是否下载成功;第二个元素是一个字典。比如:

    def item_completed(self, results, item, info):
        image_paths = [x['path'] for ok, x in results if ok]
        if not image_paths:
            raise DropItem("Item contains no images")
        item['image_paths'] = image_paths
        return item

5、在settings.py中设置条件和属性

# -*- coding: utf-8 -*-
import random
from useragent import Agent  #导入请求头,防止被ban
BOT_NAME = 'huabanSpider'

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

ITEM_PIPELINES = {
    'huaban_imagepipeline.pipelines.HuabanImagepipelinePipeline': 1,
}


# Crawl responsibly by identifying yourself (and your website) on the user-agent


USER_AGENT = '%s'%random.choice(Agent.user_agent)
#USER_AGENT = 'huaban_imagepipeline (+http://www.yourdomain.com)'

# Obey robots.txt rules
ROBOTSTXT_OBEY = True

# Configure maximum concurrent requests performed by Scrapy (default: 16)
CONCURRENT_REQUESTS = 100

# Retry many times since proxies often fail
RETRY_TIMES = 10
# Retry on most error codes since proxies fail for different reasons
RETRY_HTTP_CODES = [500, 503, 504, 400, 403, 404, 408]

# Configure a delay for requests for the same website (default: 0)
# See http://scrapy.readthedocs.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
DOWNLOAD_DELAY = 0.2
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16

# Disable cookies (enabled by default)禁止使用cookie
COOKIES_ENABLED = False
#图片存储路径
IMAGES_STORE='E:\\spider\\pictures\\huaban\\zm'
#存储缩略图
IMAGES_THUMBS = {#缩略图的尺寸,设置这个值就会产生缩略图
    'small': (50, 50),
    'big': (200, 200),
}

运行结果:
会生成2个文件夹,

图片

full:原图,
thumbs:缩略图,包含2个文件夹:big、small,

缩略图
Paste_Image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,841评论 25 707
  • Media Pipeline Scrapy为下载item中包含的文件(比如在爬取到产品时,同时也想保存对应的图片)...
    cnkai阅读 2,446评论 2 1
  • scrapy学习笔记(有示例版) 我的博客 scrapy学习笔记1.使用scrapy1.1创建工程1.2创建爬虫模...
    陈思煜阅读 12,670评论 4 46
  • 上一篇咱们讲解了Scrapy的工作机制和如何使用Scrapy爬取美女图片,而今天接着讲解Scrapy爬取美女图片,...
    qiye阅读 4,904评论 9 18
  • 又回到达州了,走在熟悉的街道,回想到爸爸,想到以前的时光,感觉爸爸的脸还在面前,难受
    叶增援阅读 61评论 0 0