纯纯的爬虫知识,python scrapy 下载中间件知多少

这篇博客咱们聊聊 scrapy 中的 Downloader Middleware ,即下载中间件相关知识。

Downloader Middlerware

首先看一下中间件在 scrapy 数据流中的位置,下图黑色箭头即下载中间件。

纯纯的爬虫知识,python scrapy 下载中间件知多少

结合上图就能看出来, RequestsResponse 都会通过 Downloader Middlerware,所以在后续代码编写的时候需要注意该点。
中间件的开启非常简单,只需要在 settings.py 文件中去除下述代码的注释即可。

DOWNLOADER_MIDDLEWARES = {
   'mid_test.middlewares.MidTestDownloaderMiddleware': 543,
}

其实 settings.py 文件仅仅是一个 scrapy 项目基础配置,除此之外,在 scrapy 框架中还存在一个 default_settings.py 文件,里面的 DOWNLOADER_MIDDLEWARES_BASE 包含更多下载中间件,而且它们是 scrapy 项目启动之后默认加载的,具体如下图所示。

纯纯的爬虫知识,python scrapy 下载中间件知多少
我们在设置 DOWNLOADER_MIDDLEWARES 的时候,需要注意优先级的问题,其原因是在后续编写自定义下载中间件时,存在 1 个 process_request() 方法和 1 个 process_response() 方法,它们会按照优先级对中间件进行排序,并按照顺序进行中间的调用。

还有一点要注意的是,如果你想要屏蔽掉 DOWNLOADER_MIDDLEWARES_BASE 中设置的中间件,需要在 DOWNLOADER_MIDDLEWARES 中给其赋值为 None 才可以,例如下述代码将屏蔽 RobotsTxtMiddleware 中间件。

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomDownloaderMiddleware': 543,
    'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': None,
}

自定义下载中间件的相关知识

本次案例编写使用的网站是 http://httpbin.org ,该站点可以直接返回请求头相关参数,测试起来非常方便。
正式编写代码前在 settings.py 文件中增加添加一个新的字段,便于输出打印日志(屏蔽了一些调试日志的输出)。

LOG_LEVEL = 'WARNING'

编写自己的下载中间件

默认请求代码如下所示,返回数据在代码下方。

import scrapy


class HbinSpider(scrapy.Spider):
    name = 'hbin'
    allowed_domains = ['httpbin.org']
    start_urls = ['http://httpbin.org/get']

    def parse(self, response):
        print(response.text)

请求目标站点之后,得到的返回数据如下所示:

纯纯的爬虫知识,python scrapy 下载中间件知多少

接下来启用中间件,然后将请求相关参数进行修改,主要操作的文件是 middlewares.py,并且要实现其中的 process_request()process_response()process_exception()spider_opened() 方法(可以仅实现一部分)。

process_request(request, spider)

通过下载中间件的每个请求,都会调用该方法。
本方法返回值必须是 NoneResponse 对象,Request 对象或者 IgnoreRequest 错误。

  • 返回 None:没啥影响,其它的请求继续处理完毕;
  • 返回 Response:直接去调用 process_response() 方法去;
  • 返回 Request:将新的 Request 加入调度队列;
  • 返回 IgnoreRequestprocess_exception() 方法被执行。

下面编写一个 UserAgentMiddlerware 中间件,替换默认中间件的同时实现自己的代理设置。
middlewares.py 文件中添加如下代码

class UserAgentMiddleware(object):

    def process_request(self, request, spider):
        request.headers.setdefault('User-Agent',
                                   'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36')

        return None

settings.py 文件中添加如下代码

DOWNLOADER_MIDDLEWARES = {
   'mid_test.middlewares.UserAgentMiddleware': 543, # 配置自己的中间件,可以修改名称为 MyUserAgentMiddleware
   'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware':None # 覆盖配置
}

如果没有覆盖原配置,会发现我们编写的中间件优先级不如 UserAgentMiddleware 高,即下图加载顺序。

纯纯的爬虫知识,python scrapy 下载中间件知多少

process_response(request, response, spider)

该方法可下载中间件在返回响应数据时,进行一些数据处理,它默认返回的是 response 对象,也可以返回 request 对象,逻辑与 process_request() 方法基本一致。

class MyUserAgentMiddleware(object):

    def process_request(self, request, spider):
        request.headers.setdefault('User-Agent',
                                   'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36')

        return None

    def process_response(self, request, response, spider):
        print(response)  # 单纯输出一下 response

        return response

process_exception(request, exception, spider)

用于处理异常,默认返回 None,也可以返回 Response 对象和 Request 对象。

一般场景都是返回 Request 对象,当出现异常时,可以重新发起请求。

内置的下载中间件

通过 scrapy 命令行可以查看所有的内置中间件。

> scrapy settings --get DOWNLOADER_MIDDLEWARES_BASE

按照优先级依次为大家介绍一下。

RobotsTxtMiddleware

查看该中间件源码了解到,当 settings.py 文件中的 ROBOTSTXT_OBEY 被设置为 True 时,尊重 robots.txt 协议。

HttpAuthMiddleware

HTTP 认证,核心逻辑如下所示:

def spider_opened(self, spider):
    usr = getattr(spider, 'http_user', '')
    pwd = getattr(spider, 'http_pass', '')
    if usr or pwd:
        self.auth = basic_auth_header(usr, pwd)

def process_request(self, request, spider):
    auth = getattr(self, 'auth', None)
    if auth and b'Authorization' not in request.headers:
        request.headers[b'Authorization'] = auth

DownloadTimeoutMiddleware

设置请求的超时时间,需要配置 settings.py 文件中的 DOWNLOAD_TIMEOUT 值,然后手动给 metadownload_timeout 参数赋值。

def process_request(self, request, spider):
   if self._timeout:
       request.meta.setdefault('download_timeout', self._timeout)

DefaultHeadersMiddleware

设置 DEFAULT_REQUEST_HEADERS 指定的默认请求头。

UserAgentMiddleware

请求的用户代理设置。

RetryMiddleware

请求重试次数。

MetaRefreshMiddleware 与 RedirectMiddleware

以上 2 个中间件都继承自 BaseRedirectMiddleware,都与重定向有关系。

HttpCompressionMiddleware

提供了对压缩(gzip, deflate)数据的支持。

CookiesMiddleware

Cookie 相关能力的支持。

HttpProxyMiddleware

代理相关设置。

DownloaderStats

下载中间件的统计信息。

HttpCacheMiddleware

为所有 HTTP 请求和响应提供低级缓存。

本篇博客内容属于 scrapy 知识铺垫,并且部分知识点在后续博客中会反复用到,请掌握。

写在后面

今天是持续写作的第 <font color=red>253</font> / 365 天。
期待 <font color=#04a9f4>关注</font>,<font color=#04a9f4>点赞</font>、<font color=#04a9f4>评论</font>、<font color=#04a9f4>收藏</font>。

更多精彩

《爬虫 100 例,专栏销售中,买完就能学会系列专栏》
[图片上传失败...(image-705322-1645358930827)]

<center>
↓ ↓ ↓ ↓一对一指导你的疑问↓ ↓ ↓ ↓</center>
<center>
↓↓↓扫码添加博主参加【78技术人社群】~Python分部↓↓↓</center>

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

推荐阅读更多精彩内容