详解scrapy内置中间件的顺序

yizhihongxing

Scrapy是一个功能强大的Python爬虫框架,它的中间件可以在爬虫运行的不同阶段进行拦截和调整请求和响应。Scrapy内置了一些中间件,这些中间件的顺序是固定的,对于新手来说,这可能会导致一些困惑和难以解决的问题。下面我将详细讲解"详解scrapy内置中间件的顺序",以及在某种情况下如何更改中间件的顺序。

Scrapy内置中间件的顺序

Scrapy内置的中间件按照以下顺序执行:

  1. Downloader Middleware:

  2. HttpCompressionMiddleware

  3. RobotsTxtMiddleware
  4. HttpAuthMiddleware
  5. DownloadTimeoutMiddleware
  6. UserAgentMiddleware
  7. RetryMiddleware
  8. RedirectMiddleware
  9. CookiesMiddleware
  10. HttpProxyMiddleware
  11. HttpErrorMiddleware
  12. RefererMiddleware
  13. MetaRefreshMiddleware
  14. HttpCompressionMiddleware

  15. Spider Middleware:

  16. DepthMiddleware

上面列举的是Scrapy框架内置中间件的顺序。其中,Downloader Middleware用于在下载器执行请求前后进行处理,Spider Middleware用于在Spider执行前后进行处理。如果想了解每个中间件的具体作用和顺序,可以参考Scrapy官方文档。

如何修改Scrapy中内置中间件的顺序

在某些情况下,我们可能需要更改Scrapy内置中间件的顺序。例如,如果我们需要在下载前设置请求头部,但是该请求头部依赖于前一个响应中的一些信息,我们需要将UserAgentMiddleware放在更前面,这样才能保证请求头在发送前被正确设置。

下面是如何在Scrapy中修改中间件的顺序:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomHttpCompressionMiddleware': 550,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
    'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 600,
    'myproject.middlewares.CustomHttpAuthMiddleware': 610,
    'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 620,
    'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 650,
    'myproject.middlewares.CustomUserAgentMiddleware': 550,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 400,
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 550,
    'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
    'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
    'scrapy.downloadermiddlewares.httperror.HttpErrorMiddleware': 800,
    'myproject.middlewares.CustomRefererMiddleware': 820,
    'scrapy.downloadermiddlewares.referer.RefererMiddleware': 840,
    'scrapy.downloadermiddlewares.metarefresh.MetaRefreshMiddleware': 900,
}

SPIDER_MIDDLEWARES = {
    'myproject.middlewares.CustomDepthMiddleware': 900,
    'scrapy.spidermiddlewares.depth.DepthMiddleware': 800,
}

上面的代码展示了如何修改Downloader Middleware和Spider Middleware的顺序。修改的方法是:将需要修改顺序的中间件的名称和优先级加入到项目的配置文件中。

例如,要将CustomUserAgentMiddleware放在UserAgentMiddleware之前,可以修改为:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomHttpCompressionMiddleware': 550,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
    'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 600,
    'myproject.middlewares.CustomHttpAuthMiddleware': 610,
    'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 620,
    'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 650,
    'myproject.middlewares.CustomUserAgentMiddleware': 400,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 400,
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 550,
    'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
    'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
    'scrapy.downloadermiddlewares.httperror.HttpErrorMiddleware': 800,
    'myproject.middlewares.CustomRefererMiddleware': 820,
    'scrapy.downloadermiddlewares.referer.RefererMiddleware': 840,
    'scrapy.downloadermiddlewares.metarefresh.MetaRefreshMiddleware': 900,
}

在上面的配置中,将CustomUserAgentMiddleware的优先级设置为400,这样就会在UserAgentMiddleware之前执行CustomUserAgentMiddleware。

示例说明

示例一:

一个常见需求是请求头设置。我们通常会使用scrapy.downloadermiddlewares.useragent.UserAgentMiddleware来设置请求头中的User-Agent字段。但是,有些网站需要在请求头中包含其他信息,例如Cookie、Referer等。这时候我们需要自定义中间件,把User-Agent和Cookie、Referer等头部信息一起设置。具体可以参考以下代码:

class CustomHeadersMiddleware(object):
    def process_request(self, request, spider):
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
            'Referer': 'https://www.google.com/',
            'Cookie': 'sessionid=123456789'
        }
        request.headers.update(headers)
        return None

其中,process_request(self, request, spider)方法会在请求被发送前自动执行,将headers中定义的键值对设置进request对象对应的headers中。

在使用自定义的请求头时,我们需要将自定义的中间件放在scrapy.downloadermiddlewares.useragent.UserAgentMiddleware之前,以保证请求头的正确配置顺序。在settings.py文件中添加如下设置:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomHeadersMiddleware': 400,
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 401,
}

示例二:

有些网站限制了请求的访问速度和频率,为此,我们需要在爬虫中添加延时设置。Scrapy中内置了scrapy.downloadermiddlewares.retry.RetryMiddleware中间件来设置请求超时重试。但是,它只会重试请求,不会添加任何延迟、等待时间的处理。所以,我们需要自定义一个中间件来添加延迟、等待时间的逻辑。具体可以参考以下代码:

import random

class CustomThrottleMiddleware(object):
    def __init__(self, delay):
        self.delay = delay

    @classmethod
    def from_crawler(cls, crawler):
        delay = crawler.settings.getint('DOWNLOAD_DELAY')
        return cls(delay)

    def process_request(self, request, spider):
        delay = random.uniform(0, self.delay)
        spider.logger.info("Delaying request for %.2f seconds..." % delay)
        time.sleep(delay)

这个中间件可以将请求延时(delay)时间之后再执行。在使用自定义的延时设置中间件时,需要将自定义的中间件放在下载中间件链的最前面,以最先执行。在settings.py文件中添加如下设置:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.CustomThrottleMiddleware': 150,
}

这里的"150"是自定义的下载中间件优先级,值越小优先级越高。若中间件中有多个,按照从上往下执行的顺序。我们使用自定义的延时设置中间件时,将其设置为比其他下载中间件更优先,以最先执行延时逻辑。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解scrapy内置中间件的顺序 - Python技术站

(0)
上一篇 2023年6月2日
下一篇 2023年6月2日

相关文章

  • 基于python实现FTP文件上传与下载操作(ftp&sftp协议)

    基于Python实现FTP文件上传与下载操作(FTP&SFTP协议) FTP(文件传输协议)是一种用于向互联网上传送文件的标准协议,而SFTP(SSH文件传输协议)则是FTP的安全替代。在Python中,通过ftplib库,我们可以使用FTP协议上传和下载文件,通过paramiko库,我们可以使用SFTP协议进行同样的操作。 本文将详细介绍如何基于P…

    python 2023年6月5日
    00
  • Python采集某度贴吧排行榜实战示例

    Python采集某度贴吧排行榜实战示例 前言 网页上的数据采集在现在的数据处理中占用了重要的地位,而Python作为一种通用的编程语言,在数据处理中也占用了很大的优势。下面,我们将介绍采集某度贴吧排行榜的实战示例。 准备工作 在开始操作之前,需要先安装一些Python库: pip install requests pip install beautifuls…

    python 2023年6月3日
    00
  • python集合删除多种方法详解

    Python集合删除多种方法详解 在Python中,集合是一种常用的数据类型。当我们需要从集合中删除元素时,会有多种方法可供选择。本文将详细讲解这些方法及其使用场景。 方法一:remove() remove()方法可以从集合中删除指定的元素,如果指定元素不存在则会抛出KeyError异常。示例代码如下: fruits = {"apple"…

    python 2023年5月13日
    00
  • python的函数和方法(中)

    Python的函数和方法(中): 在Python中,函数和方法是两个重要的概念。函数是一个独立的代码块,可被多次调用,用于完成一定的功能。方法是对象中的函数,它是一个与对象相关联的函数。本文将探讨Python中函数和方法的更多知识点。 函数参数: Python中函数的参数可以有默认值,也可以为可变参数。默认值参数表示,当函数没有传递这个参数时,它使用默认值。…

    python 2023年6月5日
    00
  • 如何基于python测量代码运行时间

    当我们优化代码或者比较算法的效率时,了解代码运行所需时间是非常重要的。Python提供了一种方法来测量代码运行时间。在本文中,我们将讨论Python中测量代码运行时间的方法。 time库 Python内置time库,可以用于测量代码执行所需时间。具体步骤如下: 使用time模块中的time()函数记录当前时间作为开始时间。 执行要计时的代码。 再次使用tim…

    python 2023年6月3日
    00
  • 带有变量赋值的 Python 隐式 if 语句——这是如何工作的? [复制]

    【问题标题】:Python Implicit if statement with variable assignment — How does this work? [duplicate]带有变量赋值的 Python 隐式 if 语句——这是如何工作的? [复制] 【发布时间】:2023-04-02 05:08:01 【问题描述】: 我在上个月开始学习 p…

    Python开发 2023年4月8日
    00
  • Python ValueError: invalid literal for int() with base 10 实用解决方法

    Python中的ValueError异常通常是由于数据类型不匹配,或者输入数据格式错误等原因引起的。其中,invalid literal for int() with base 10错误表示给int()函数传递了无效参数。本篇攻略将针对此错误进行详细讲解,提供实用解决方法,希望能帮助您排除类似问题。 什么是PythonValueError: invalid …

    python 2023年5月13日
    00
  • 关于Python函数的定义和参数

    操作步骤: Python函数的定义 在Python中,函数是一段可重用的代码块,用于执行特定的操作。函数在许多情况下被称为方法或过程。 函数的语法 函数定义的基本语法如下: def function_name(parameters): """函数docstring部分""" # 函数体部分 retu…

    python 2023年5月13日
    00
合作推广
合作推广
分享本页
返回顶部