Tool

Alarm

基于 gsender 模块的内置报警
提供两个函数

  • send_email:发送邮件
  • send_dingtalk:支持所有钉钉群聊消息类型

注意:

  • 模块需要主动调用
  • 钉钉消息考虑到模板较多,所以返回的是 DingTalkSender 对象,再去调用对应的发送方法

设置

# 预警:Email
EMAIL_USER = None  # Email 账号
EMAIL_PWD = None  # Email 授权码

# 预警:DingTalk
DING_TALK_SECRET = None  # 加签
DING_TALK_ACCESS_TOKEN = None  # webhook 链接内的 access_token

示例

基本使用

import palp

palp.send_email(receiver='xxx', content_text='palp 执行结束')
palp.send_dingtalk().send_text(content='测试消息')

实际案例

比如在 middleware 中的 request_record 中发送处理结果

def request_record(self, spider, record: dict) -> None:
    """
    请求结果记录(在 spider 结束时调用)

    :param spider:
    :param record: {'all': 0, 'failed': 0, 'succeed': 0} 样式的字典
    :return:
    """
    request_all = record['all']
    request_failed = record['failed']
    request_succeed = record['succeed']

    palp.send_dingtalk().send_text(
        content=f'执行完毕,当前处理情况:\n总量:{request_all}\n失败量:{request_failed}\n成功量:{request_succeed}'
    )

Checker

根据一定条件控制爬虫暂停、停止运行

参数

可配置参数:

  • check_time:检查的频率,默认 3s
  • failed_limit:检查的容错,默认 3 次,连续 3 次就执行对应函数

修改

Checker.check_time = 1
Checker.failed_limit = 1

自定义 need_stop

仅需重写 need_stop 方法,并返回 bool
注意:该函数如果产生任何报错,将视为 True 需要暂停、停止,所以要做好处理

class Checker(palp.Checker):
    @classmethod
    def need_stop(cls) -> bool:
        return True # 何时需要停止

调用

一般在 request_in 时使用,直接阻断所有新请求

可选函数:

  • check_and_wait:当连续错误达到 failed_limit 之后,阻拦所有请求,直到释放
  • check_and_stop:当连续错误达到 failed_limit 之后,停止所有新请求的处理(一旦中断无法挽回,只能重启)
  • stop_spider:停止所有新请求的处理(使用以上方法,不需要主动调用)

注意:

  • 暂时分布式时,检查函数会调用多次
  • 内部是调用的 _need_stop() 函数,所以可以控制频率、容错
  • 这里的停止是温和的,只是阻断新请求从队列中接收
  • check_and_wait 的 timeout 非精确时间,受 check_time 影响会有一定误差

案例

当百度访问状态码不是 200 时,将会停止 spider 函数执行,直到访问是 200

class Checker(palp.Checker):
    check_time = 3      # 多少 s 检查一次
    failed_limit = 3    # 连续多少次就执行 wait、stop

    @classmethod
    def need_stop(cls) -> bool:
        if requests.get('http://www.baidu.com').status_code != 200:
            return True

        return False

class CheckRequestMiddleware(palp.RequestMiddleware):
    def request_in(self, spider, request) -> None:
        Checker.check_and_wait(spider=spider)    # 连续 3 次失败将会阻拦所有请求,直到状态恢复
        Checker.check_and_wait(spider=spider, timeout=1*60*60)    # 连续 3 次失败将会阻拦所有请求,达到指定超时时间停止 spider,避免死循环
        Checker.check_and_stop(spider=spider)    # 连续 3 次失败将会停止 spider 执行