Scrapy--下载器中间件(Downloader Middleware)


pingan
平安喜乐 2022-09-21 09:16:19 50282
分类专栏: 资讯

目录

下载器中间件简介

自定义下载器中间件

RandomUserAgentMiddleware

RandomProxyMiddleware

激活下载器中间件

内置下载器中间件

CookiesMiddleware

DefaultHeadersMiddleware

DownloadTimeoutMiddleware

HttpProxyMiddleware

RedirectMiddleware

RetryMiddleware

RobotsTxtMiddleware

UserAgentMiddleware


下载器中间件简介

下载器中间件(Downloader Middleware)是介于Scrapy的request/response处理的钩子框架。 是用于全局修改Scrapy request和response的一个轻量、底层的系统。

自定义下载器中间件

每个下载器中间件是一个定义了以下一个或多个方法的Python类:

  1. def process_request(self, request, spider):
  2. 每一个Requests 从引擎传递给下载器之前,该方法被调用
  3. 必须返回下述值之一:
  4. - None: Scrapy将继续处理该request,由其他的下载器中间件(按照顺序编号由小到大)或者下载器处理;
  5. - Response: 其将返回该response ;
  6. 其他下载器中间件的 process_request() 或 process_exception() 方法 以及 下载器的下载函数将不会被调用;
  7. 已经激活的下载器中间件将按照顺序编号由大到小依次调用 process_response() 方法对该response进行处理;
  8. - Request: Scrapy 将停止调用 process_request() 方法并重新调度返回的request
  9. - raise IgnoreRequest: 声明忽略该request;
  10. 已经激活的下载器中间件将按照顺序编号由大到小依次调用 process_exception() 方法对该异常进行处理;
  11. 如果没有任何一个方法处理该异常, 则request的errback(Request.errback)方法会被调用;
  12. 如果没有代码处理抛出的异常, 则该异常被忽略且不记录(不同于其他异常那样)。
  13. return None
  14. def process_response(self, request, response, spider):
  15. 每一个Responses 从下载器返回给引擎之前,该方法被调用
  16. 必须返回下述值之一:
  17. - Response: 可以与传入的response相同,也可以是全新的对象 ;
  18. 已经激活的比当前中间件顺序编号小的下载器中间件将按照顺序编号由大到小依次调用 process_response() 方法对该response进行处理;
  19. - Request: Scrapy 将停止调用 process_request() 方法并重新调度返回的request
  20. - raise IgnoreRequest: 声明忽略该request;
  21. 则调用request的errback(Request.errback)。 如果没有代码处理抛出的异常,则该异常被忽略且不记录(不同于其他异常那样);
  22. return response
  23. def process_exception(self, request, exception, spider):
  24. 当下载器或者下载器中间件执行 process_request() 方法抛出异常时,该方法被调用
  25. 必须返回下述值之一:
  26. - None: Scrapy将继续处理该异常;
  27. 已经激活的下载器中间件将按照顺序编号由大到小依次调用 process_exception() 方法对该异常进行处理;
  28. 直到所有下载器中间件都被调用完毕,则调用默认的异常处理;
  29. - Response: 已经激活的下载器中间件将按照顺序编号由大到小依次调用 process_response() 方法对该response进行处理;
  30. - Request: Scrapy 将停止异常处理并重新调度返回的request
  31. pass

RandomUserAgentMiddleware

 RandomUserAgentMiddleware能够从我们预先定义好的User-Agent列表中随机选择一个添加到Request的请求头中。

  1. import random
  2. 随机选择 User-Agent 下载器中间件
  3. class RandomUserAgentMiddleware(-title class_ inherited__">object):
  4. def process_request(self, request, spider):
  5. 从 settings 的 USER_AGENTS 列表中随机选择一个作为 User-Agent
  6. user_agent = random.choice(spider.settings['USER_AGENTS'])
  7. request.headers['User-Agent'] = user_agent
  8. return None
  9. def process_response(self, request, response, spider):
  10. 验证 User-Agent 设置是否生效
  11. print(request.headers['User-Agent'])
  12. return response

 settings.py 中配置的 USER_AGENTS 列表内容格式如下:

  1. USER_AGENTS = [
  2. "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
  3. "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.120 Safari/535.2"
  4. ]

RandomProxyMiddleware

在网络爬虫过程中,经常会碰到 IP地址被限制访问的情况,我们通常都会通过设置代理来解决。

RandomProxyMiddleware就是这样一个下载器中间件,能够从我们预先定义好的IP代理列表中随机选择一个来发送请求。

  1. import random
  2. 随机选择 IP 代理下载器中间件
  3. class RandomProxyMiddleware(-title class_ inherited__">object):
  4. 从 settings 的 PROXIES 列表中随机选择一个作为代理
  5. def process_request(self, request, spider):
  6. proxy = random.choice(spider.settings['PROXIES'])
  7. request.meta['proxy'] = proxy
  8. return None

 settings.py 中配置的 PROXIES 列表内容格式如下:

  1. PROXIES = [
  2. "https://171.13.92.212:9797",
  3. "https://164.163.234.210:8080",
  4. "https://143.202.73.219:8080",
  5. "https://103.75.166.15:8080"
  6. ]

激活下载器中间件

要激活下载器中间件,需要将其加入到 DOWNLOADER_MIDDLEWARES 设置中。 该设置是一个字典(dict),键为中间件类的路径,值为其中间件的顺序(order)。

激活 RandomUserAgentMiddleware 和 RandomProxyMiddleware 两个下载器中间件的配置如下:

  1. Enable or disable downloader middlewares
  2. See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
  3. DOWNLOADER_MIDDLEWARES = {
  4. 'baidu_tieba.middlewares.RandomUserAgentMiddleware': 541,
  5. 'baidu_tieba.middlewares.RandomProxyMiddleware': 542
  6. }

DOWNLOADER_MIDDLEWARES 设置会与Scrapy定义的 DOWNLOADER_MIDDLEWARES_BASE 设置合并(但不是覆盖), 而后根据顺序(order)进行排序,最后得到启用中间件的有序列表: 第一个中间件是最靠近引擎的,最后一个中间件是最靠近下载器的。

关于如何分配中间件的顺序请查看 DOWNLOADER_MIDDLEWARES_BASE 设置,而后为你的中间件选择一个合适的顺序(order)值。 由于每个中间件执行不同的动作,你的中间件可能会依赖于之前(或者之后)执行的中间件,因此顺序是很重要的。

以下是 DOWNLOADER_MIDDLEWARES_BASE 的默认配置:

  1. DOWNLOADER_MIDDLEWARES_BASE = {
  2. 'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 100,
  3. 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 300,
  4. 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 350,
  5. 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 400,
  6. 'scrapy.downloadermiddlewares.retry.RetryMiddleware': 500,
  7. 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': 550,
  8. 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': 580,
  9. 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
  10. 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
  11. 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
  12. 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
  13. 'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware': 830,
  14. 'scrapy.downloadermiddlewares.stats.DownloaderStats': 850,
  15. 'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': 900,
  16. }

如果你想禁止内置的(在 DOWNLOADER_MIDDLEWARES_BASE 中设置并默认启用的)中间件, 你可以在项目的 DOWNLOADER_MIDDLEWARES 设置中定义该中间件,并将其值赋为 None 。 例如,关闭内置的 UserAgentMiddleware 中间件:

  1. DOWNLOADER_MIDDLEWARES = {
  2. 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None
  3. }

最后,请注意,有些中间件需要通过特定的设置来启用。更多内容请查看相关中间件文档

内置下载器中间件

接下来将对几个常用的内置下载器中间件进行简单介绍。 

CookiesMiddleware

class scrapy.downloadermiddlewares.cookies.CookiesMiddleware

 内置的 CookiesMiddleware 下载器中间件使得爬取需要cookie(例如使用session)的网站成为了可能。 其追踪了web server发送的cookie,并在之后的request中发送回去, 就如浏览器所做的那样。

以下设置可以用来配置CookiesMiddleware中间件:

  1. COOKIES_ENABLED = True 是否启用 CookiesMiddleware ,默认 True
  2. COOKIES_DEBUG = False 是否启用 Cookies 调试,默认 False

 如果启用 Cookies 调试,Scrapy将记录所有在request(Cookie 请求头)发送的cookies及response接收到的cookies(Set-Cookie 接收头)。

下边是启用 COOKIES_DEBUG 的记录的样例:

  1. 2011-04-06 14:35:10-0300 [scrapy] INFO: Spider opened
  2. 2011-04-06 14:35:10-0300 [scrapy] DEBUG: Sending cookies to: <GET http://www.diningcity.com/netherlands/index.html>
  3. Cookie: clientlanguage_nl=en_EN
  4. 2011-04-06 14:35:14-0300 [scrapy] DEBUG: Received cookies from: <200 http://www.diningcity.com/netherlands/index.html>
  5. Set-Cookie: JSESSIONID=B~FA4DC0C496C8762AE4F1A620EAB34F38; Path=/
  6. Set-Cookie: ip_isocode=US
  7. Set-Cookie: clientlanguage_nl=en_EN; Expires=Thu, 07-Apr-2011 21:21:34 GMT; Path=/
  8. 2011-04-06 14:49:50-0300 [scrapy] DEBUG: Crawled (200) <GET http://www.diningcity.com/netherlands/index.html> (referer: None)
  9. [...]

DefaultHeadersMiddleware

class scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware

该中间件设置 DEFAULT_REQUEST_HEADERS 指定的默认request header

  1. Override the default request headers:
  2. DEFAULT_REQUEST_HEADERS = {
  3. 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  4. 'Accept-Language': 'en',
  5. }

DownloadTimeoutMiddleware

class scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware

该中间件设置 DOWNLOAD_TIMEOUT 指定的request下载超时时间。

  1. 下载器超时时间(单位: 秒),默认 180
  2. DOWNLOAD_TIMEOUT = 180

HttpProxyMiddleware

class scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware

该中间件提供了对request设置HTTP代理的支持。你可以通过在 Request 对象中设置 proxy 元数据来开启代理。

类似于Python标准库模块 urllib 及 urllib2 ,其使用了下列环境变量:

  1. http_proxy
  2. https_proxy
  3. no_proxy

你也可以针对每个请求设置 proxy 元数据, 其形式类似于 http://some_proxy_server:port 。

RedirectMiddleware

class scrapy.downloadermiddlewares.redirect.RedirectMiddleware

该中间件根据response的状态处理重定向的request。

通过该中间件的(被重定向的)request的url可以通过 Request.meta 的 redirect_urls 键找到。

RedirectMiddleware 可以通过下列设置进行配置(更多内容请参考设置文档):

  1. REDIRECT_ENABLED 是否启用RedirectMiddleware中间件,默认: True
  2. REDIRECT_MAX_TIMES 单个request被重定向的最大次数,默认: 20

如果 Request.meta 包含 dont_redirect 键,则该request将会被此中间件忽略。

RetryMiddleware

class scrapy.downloadermiddlewares.retry.RetryMiddleware

该中间件将重试可能由于临时的问题,例如连接超时或者HTTP 500错误导致失败的页面。

爬取进程会收集失败的页面并在最后,spider爬取完所有正常(不失败)的页面后重新调度。 一旦没有更多需要重试的失败页面,该中间件将会发送一个信号(retry_complete), 其他插件可以监听该信号。

RetryMiddleware 可以通过下列设定进行配置 (更多内容请参考设置文档):

  1. RETRY_ENABLED 是否启用 RetryMiddleware ,默认: True
  2. RETRY_TIMES 包括第一次下载,最多的重试次数,默认: 2
  3. RETRY_HTTP_CODES 重试的response 返回值(code),默认: [500, 502, 503, 504, 400, 408]

关于HTTP错误的考虑:

如果根据HTTP协议,您可能想要在设定 RETRY_HTTP_CODES 中移除400错误。 该错误被默认包括是由于这个代码经常被用来指示服务器过载(overload)了。而在这种情况下,我们想进行重试。

如果 Request.meta 包含 dont_retry 键, 该request将会被本中间件忽略。

RobotsTxtMiddleware

class scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware

该中间件过滤所有robots.txt eclusion standard中禁止的request。

确认该中间件及 ROBOTSTXT_OBEY 设置被启用以确保Scrapy尊重robots.txt。

  1. Obey robots.txt rules,默认 True
  2. ROBOTSTXT_OBEY = False

UserAgentMiddleware

class scrapy.downloadermiddlewares.useragent.UserAgentMiddleware

用于覆盖spider的默认 User-Agent 的中间件。

要使得spider能覆盖默认的 User-Agent,其 USER_AGENT 属性必须被设置。

  1. Crawl responsibly by identifying yourself (and your website) on the user-agent
  2. USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'

参考文章

https://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/downloader-middleware.html

 

文章知识点与官方知识档案匹配,可进一步学习相关知识
Python入门技能树网络爬虫Scrapy框架127519 人正在系统学习中

网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。

本文链接:https://www.xckfsq.com/news/show.html?id=8734
赞同 0
评论 0 条
平安喜乐L0
粉丝 0 发表 6 + 关注 私信
上周热门
如何使用 StarRocks 管理和优化数据湖中的数据?  2962
【软件正版化】软件正版化工作要点  2881
统信UOS试玩黑神话:悟空  2848
信刻光盘安全隔离与信息交换系统  2740
镜舟科技与中启乘数科技达成战略合作,共筑数据服务新生态  1274
grub引导程序无法找到指定设备和分区  1239
华为全联接大会2024丨软通动力分论坛精彩议程抢先看!  165
2024海洋能源产业融合发展论坛暨博览会同期活动-海洋能源与数字化智能化论坛成功举办  164
点击报名 | 京东2025校招进校行程预告  164
华为纯血鸿蒙正式版9月底见!但Mate 70的内情还得接着挖...  159
本周热议
我的信创开放社区兼职赚钱历程 40
今天你签到了吗? 27
信创开放社区邀请他人注册的具体步骤如下 15
如何玩转信创开放社区—从小白进阶到专家 15
方德桌面操作系统 14
我有15积分有什么用? 13
用抖音玩法闯信创开放社区——用平台宣传企业产品服务 13
如何让你先人一步获得悬赏问题信息?(创作者必看) 12
2024中国信创产业发展大会暨中国信息科技创新与应用博览会 9
中央国家机关政府采购中心:应当将CPU、操作系统符合安全可靠测评要求纳入采购需求 8

加入交流群

请使用微信扫一扫!