Scrapy(三) - Spider Middlerware 使用

介绍

处于Spider 和 Engine 之间的处理模块。当Downloader 生成Response之后,Response会被发送给Spider,在发送
给Spider之前,Response 会首先经过Spider Middleware的处理,当Spider处理生成Item和 Request 之后,Item
和Request 还会经过Spider Middlerware 的处理

主要有以下三个作用:

  • Downloader 生成Response 之后,Engine 会将其发送给Spider 进行解析,在Response 发送给Spider之前,
    可以借助Spider Middlerware 对Response 进行处理

  • Spider 生成Request 之后会被发送至Engine,然后Request 会被转发到Scheduler,在Request被发送给Engine之前,
    可以借助Spider Middlerware 对 Request进行处理

  • Spider 生成Item之后会被发送至Engine,然后Item 会被转发到Item pipeline,在Item 被发送给Engine之前,可以借助
    Spider Middlerware 对Item进行处理

框架默认提供的Scrapy Middler:

数字越小的Spiddler Middlewre 越靠近Engine,数字越大的越靠近Spider,优先级和 Downloader Middleware一致

每个Spider Middlerware 都定义了以下一个或多个方法的类,核心方法有如下4个

  • process_spider_input(response,spider)
  • process_spider_output(response,result,spider)
  • process_spider_exception(response,exception,spider)
  • process_start_requests(start_requests,spider)

只需要实现其中一个方法就可以定义一个Spider Middlerware。

核心方法介绍

  • process_spider_input(response,spider)

当Response 通过 Spider Middleware 时,process_spider_input方法被调用,处理该Response。
应该返回None,或者抛出一个异常

  • 如果返回None,Scrapy会继续处理该Response,调用其他的Spider Middleware 知道Spider 处理该
    Response

  • 如果它抛出一个异常,Scrapy不会调用任何其他Spider Middleware 的process_spider_input方法,并调用
    Request 的errback方法。errback的输出将会以另一个方向被重新输入中间件,使用process_spider_output方法来处理,当
    其抛出异常时则调用process_spider_exception来处理

实战

process_start_requests

spider:

import scrapy
from scrapy import Request

from scrapyspidermiddlerwaredemo.items import DemoItem


class HttpbinSpider(scrapy.Spider):
    name = 'httpbin'
    allowed_domains = ['www.httpbin.org']
    start_url = 'https://www.httpbin.org/get'


    def start_requests(self):
        for i in range(5):
            url = f'{self.start_url}?query={i}'
            yield Request(url, callback=self.parse)

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

process_start_requests: 请求spider的初始请求

class CustomizeMiddlerware(object):
    def process_start_requests(self, start_requests, spider):
        '''
        处理start_url
        :param start_requests:
        :param spider:
        :return:
        '''
        for request in start_requests:
            url = request.url
            url += '&name=tom'
            request = request.replace(url=url)
            yield request

输出结果:可以看到请求的url 已被修改

process_spider_input

HttpbinSpider - parse() 方法:

    def parse(self, response):
        print(f'response status:{response.status}')
        print(response.text)

CustomizeMiddlerware - process_start_requests

class CustomizeMiddlerware(object):
    def process_start_requests(self, start_requests, spider):
        '''
        处理spider 开始时的request
        :param start_requests:
        :param spider:
        :return:
        '''
        for request in start_requests:
            url = request.url
            url += '&name=tom'
            request = request.replace(url=url)
            yield request

    def process_spider_input(self, response, spider):
        '''
        处理 Response,修改响应码
        :return:
        '''
        response.status = 201

输出结果:可以看到响应状态码已被修改

process_spider_output

parse:

    def parse(self, response):
        print(f'response status:{response.status}')
        item = DemoItem(**response.json())
        yield item

CustomizeMiddlerware - process_spider_output:

class CustomizeMiddlerware(object):
    def process_spider_output(self, response, result, spider):
        '''
        处理Item对象
        :param response:
        :param result:
        :param spider:
        :return:
        '''
        for i in result:
            if isinstance(i, DemoItem):
                i['origin'] = None
                yield i

输出结果:

posted @ 2022-12-16 21:34  chuangzhou  阅读(98)  评论(0编辑  收藏  举报