bricks
开发指南
2.1 事件
2.1.3 事件开发

1. 事件回调开发

事件回调函数实际上就是一个普通的函数 / 实例方法 / 类方法 / 静态方法,因此回调函数的开发即开发普通的函数,如以下为内置过滤无效状态码等简单的事件函数源码。

 
from bricks.core import signals  
from bricks.core.context import Context
 
def is_success():  
    """  
    通用的判断响应是否成功  
  
    :return:  
    """    
    context: Context = Context.get_context()  
    response = context.obtain("response")  
    if not response.ok:  
        raise signals.Retry
 
 

从以上源码我们需要了解的内容是:

  1. 我们主要操作的对象就是 contextContext 是爬虫请求过程中的上下文对象,通过该对象,我们可以获取到他的请求/响应等数据
  2. 只有运行到一定的流程,Context 的属性才会被赋值,例如,只有在完成请求后,才会有 response 属性
  3. 针对 Context 对象进行相应操作之后,如果要改变运行流程,则需要 raisesignals 信号;比较常用的信号如下
    1. signals.Retry: 重试信号,会中断当前流程并重试请求
    2. signals.Success: 成功信号,会中断当前流程并删除种子
    3. signals.Failure: 失败信号,会中断当前流程并将种子暂时放入 failure 队列
  4. 大体的时间,返回的信号导致的结果是类似的,但是部分环节的事件可能不会处理某些信号,例如初始化的时间和爬虫的事件其实是有细微差别的

2. 事件回调注册

内置接口注册

事件函数一般在 install 接口进行注册,该接口在实例生成的时候会自动调用一次,我们可以看看内置的 air.Spiderinstall 方法,就会默认注册一些事件。

 
def install(self):  
    super().install()  
    self.use(  
        state.const.BEFORE_REQUEST,  
        {"func": on_request.Before.fake_ua},  
        {"func": on_request.Before.set_proxy, "index": math.inf},  
    )  
    self.use(  
        state.const.AFTER_REQUEST,  
        {"func": on_request.After.show_response},  
        {"func": on_request.After.conditional_scripts},  
        {"func": on_request.After.is_success}  
    )
 
 

注册时间使用的是 use 方法

装饰器注册

除了可以使用内置接口注册,还可以使用装饰器注册,方法如下

from bricks import const
from bricks.core import signals, events
 
 
@events.on(const.BEFORE_PIPELINE)  
def test():  
    context: Context = Context.get_context()  
    print(context)

类下的方法同样是支持的

关于 on 函数说明

使用装饰器的方式注册事件 ,如果有 staticmethod 之类的装饰器, 则需要紧贴着你的函数

  • :param binding: 事件作用对象, 默认为自动判断
    如果是类相关的方法(静态方法, 类方法, 实例方法), 则会作用于该类的实例
    如果是普通函数(则会作用于全局)
    如果传入了对象, 则仅作用于该对象

  • :param form: 事件类型, 可以传入 const 属性

  • :param index: 事件排序, 默认会在最后注册执行, 按照代码顺序索引一次递增, 索引越大, 执行速度越靠后

  • :param disposable: 是否为可弃用事件(仅运行一次)

3. 事件回调取消

有时候如果需要取消事件,可以使用以下方法,但是一般用不上

from bricks import const
from bricks.spider import air
 
class MySpider(air.Spider):
	pass
 
 
 
if __name__ == '__main__':  
    spider = MySpider()  
    for i in spider.plugins:  
        if i.form == const.BEFORE_PIPELINE and i.task.func == spider.is_success:  
            i.unregister()