【Python自学笔记】爬虫必备!Scrapy下载中间件DownloaderMiddleware的使用方法!

文章目录

  • DownloaderMiddleware 下载中间件
    • process_request 方法
    • process_response 方法
    • process_exception 方法


  • 返回主目录

DownloaderMiddleware 下载中间件

【Python自学笔记】爬虫必备!Scrapy下载中间件DownloaderMiddleware的使用方法!_第1张图片

从上图可以看到DownloaderMiddleware所处的位置在调度器发送请求和返回响应的中途,所以我们可以通过设置下载中间件来更改 Scrapy 的请求和响应。

  • 要使用下载中间件,首先我们需要在settings.py文件中将其激活,如下
    启动中间件
  • 要实现更改 Scrapy 的请求和响应,我们可以通过以下几个方法来完成!
  • 这里需要注意谨慎返回Request

process_request 方法

    def process_request(self, request, spider):
        return None
  • 通过下载中间件的每个请求都会调用此方法,且必须return返回NoneResponse对象Request 对象,或 raise IgnoreRequest中的一个!
返回 说明
None Scrapy 将继续处理这个请求,执行所有其他中间件,直到最终调用适当的下载器处理程序执行请求(并获取其响应
Response对象 Scrapy 将不再调用其他process_request()方法process_exception()方法,也不会启动下载器;而是直接返回那个响应。但是仍然会经过process_response() 方法如果需要使用selenium等工具来加载JS的话就可以在这里直接返回获取到的响应(body=browser.page_source
Request 对象 Scrapy 将终止当前流程,终止调用其他process_request方法将request返回给调度器,大多数情况是用于更换新的request请求
raise IgnoreRequest 抛出IgnoreRequest异常, 该异常就会交个process_exception()方法进行处理; 如果没有任何一个方法处理该异常,就会调用Request()请求设定的errback参数对应的回调函数处理(参考下列示例);如何仍然没有代码处理这个异常,那么该请求就会直接被忽略, 也不会记录在错误日志中
  • Request()请求中设定的errback对应的回调函数,官方示例
#!/usr/bin/env python
# -*- encoding: utf-8 -*-                            
# @Author     : xiao qiang
# @WeChat     : xiaoqiangclub                              
# @Software   : PyCharm      
# @File       : test005.py
# @Time       : 2021/6/11 13:57
def parse(self, response):
    request = scrapy.Request('http://www.example.com/index.html',
                             callback=self.parse_page2,
                             errback=self.errback_page2,
                             cb_kwargs=dict(main_url=response.url))
    yield request

def parse_page2(self, response, main_url):
    pass

def errback_page2(self, failure):
    yield dict(
        main_url=failure.request.cb_kwargs['main_url'],
    )
  • 这里需要注意:
    1. process_request()方法在返回Request对象的情况下,最好是添加一个判断(或者添加dont_filter=False),否则容易造成死循环!
    2. 返回Request的时候(请求同一个网址)需要把dont_filter=True加上,不然scrapy会自动过滤掉已经请求过的网页!
  • 这里顺便说一下如何在中间件修改请求地址:我们可以从官方文档中得知request.url是一个只读值,不允许修改!如果我们需要修改的话可以使用request.replace(),如下
import scrapy
import requests


class TestMiddleware:
    def process_request(self, request, spider):
        print('进入process_request...')
        url = 'https://www.baidu.com'
        r = requests.get('https://www.baidu.com')
        if request.url == 'https://httpbin.org/ip':  # 添加一个判断,否则会造成死循环!
            # return scrapy.http.Request(url)  # 返回Request对象,也可以直接写成:scrapy.Request(url)
            # return scrapy.http.Response(url=url, status=200,
            #                             body=r.content)  # 返回Response对象,body必须是一个bytes类型,可以使用status来自定义响应代码
            request = request.replace(url=url)  # 修改请求url
            return request

        # return scrapy.http.Request(request.url, dont_filter=False)  # 添加 dont_filter=False,防止死循环!
        return None
        # raise IgnoreRequest  # 抛出异常,会传递到process_exception()方法处理

process_response 方法

	def process_response(self, request, response, spider):
        return response
  • process_response()方法需要return返回Response对象Request 对象,或 raise IgnoreRequest中的一个!
返回 说明
Response对象 返回一个Response对象,它可以是原来的response,也可能是我们修改过的response;其他流程正常执行!
Request 对象 与process_request方法相同,Scrapy 将终止当前流程,终止调用其他process_request方法将request返回给调度器
raise IgnoreRequest 抛出IgnoreRequest异常, 该异常就会调用Request()请求设定的errback参数对应的回调函数处理(参考process_request()方法中的示例)`;如何没有代码处理这个异常,那么它会直接被忽略, 也不会记录在错误日志中
  • 这里需要注意:
    1. process_response()方法在返回Request对象的情况下,最好是添加一个判断(或者添加dont_filter=False),否则容易造成死循环!
    2. 返回Request的时候(请求同一个网址)需要把dont_filter=True加上,不然scrapy会自动过滤掉已经请求过的网页!
  • 示例代码
    def process_response(self, request, response, spider):
        print('进入process_response...')
        url = 'https://www.baidu.com'
        r = requests.get('https://www.baidu.com')
        # return scrapy.http.Response(url=url, body=r.content, status=200)  # 自定义一个新的response返回
        # return scrapy.http.Request(url=url, dont_filter=False)  # 返回一个Request对象
        # raise IgnoreRequest     # 抛出异常, 调用Request()请求设定的errback参数对应的回调函数处理

        return response

process_exception 方法

	def process_exception(self, request, exception, spider):
  • 下载处理程序process_request()(下载器中间件)引发异常(包括IgnoreRequest异常)时,Scrapy 会调用process_exception()方法。可以return返回NoneResponse对象或者Request对象
返回 说明
None Scrapy 将调用其他的process_exception()方法继续处理这个异常
Response对象 Scrapy会将Response对象交给process_response()方法继续处理,且不再执行其他的process_exception()方法
Request 对象 Scrapy将终止当前流程,将request返回给调度器
  • 这里需要注意:
    1. process_response()方法在返回Request对象的情况下,最好是添加一个判断(或者添加dont_filter=False),否则容易造成死循环!
    2. 返回Request的时候(请求同一个网址)需要把dont_filter=True加上,不然scrapy会自动过滤掉已经请求过的网页!
  • 示例代码
    def process_exception(self, request, exception, spider):
        print('进入process_exception...')
        url = 'https://www.baidu.com'
        r = requests.get('https://www.baidu.com')
        return scrapy.http.Response(url=url, body=r.content, status=200)  # 自定义一个新的response返回
        # return scrapy.http.Request(url=url, dont_filter=False)  # 返回一个Request对象
        # return None
  • 返回主目录
  • 更多内容请参考官方文档
  • 更多内容

你可能感兴趣的:(自学笔记,python,scrapy,爬虫,下载中间件,request)