4 种 SERP 监控告警方式对比:Slack / Email / Webhook / SMS

背景

做 SERP 监控需要告警,Slack / Email / Webhook / SMS 各有取舍。

4 种方式对比

1. Slack

python 复制代码
def alert_slack(text):
    requests.post(SLACK_WEBHOOK, json={
        "blocks": [
            {"type": "section", "text": {"type": "mrkdwn", "text": text}}
        ]
    })

优点:实时(秒级)、富文本块、thread 回复、@提醒 缺点:依赖 Slack,团队需 Slack 账号

2. Email

python 复制代码
def alert_email(to, subject, body):
    import smtplib
    from email.mime.text import MIMEText
    msg = MIMEText(body)
    msg["Subject"] = subject
    msg["To"] = to
    with smtplib.SMTP("smtp.gmail.com", 587) as s:
        s.starttls()
        s.login(USER, PASS)
        s.send_message(msg)

优点:通用,不需要装 app,异步不阻塞 缺点:延迟(分钟级)、易进垃圾箱、HTML 渲染差

3. Webhook

python 复制代码
def alert_webhook(url, payload):
    requests.post(url, json=payload, timeout=5)

优点:通用(JSON 任意接收方)、可路由到不同系统 缺点:需要接收端,失败重试要自己做

4. SMS(短信)

python 复制代码
def alert_sms(to, text):
    from twilio.rest import Client
    client = Client(TWILIO_SID, TWILIO_TOKEN)
    client.messages.create(
        from_="+1234567890", to=to, body=text
    )

优点:无网也能收、紧急最高优先级 缺点:贵(每条 $0.01+)、字符限制 160、有 spam filter

4 种方式实测(我项目 30 天)

指标 Slack Email Webhook SMS
到达延迟 1-3s 30-300s 1-5s 5-30s
到达率 99% 90% 99%(自己控制) 95%
成本/月 $0 $0 $0 $5+
字符限制 40k 无 无 160
异步支持 ✓ ✓ ✓ ✗
富文本 ✓(blocks) ✓(HTML) JSON 自由 ✗
团队协作 ✓(thread) ✗ ✗ ✗
移动端 ✓(app) ✓(mail app) ✗ ✓(SMS)

选型

场景 选
团队用 Slack Slack
非开发人员 Email
接自己系统 Webhook
紧急高优 SMS

5 个工程细节

1. 降级(主通道失败,备用)

python 复制代码
def alert_with_fallback(text):
    try:
        alert_slack(text)
    except Exception:
        try:
            alert_webhook(BACKUP_WEBHOOK, {"text": text})
        except Exception:
            alert_email(EMERGENCY_EMAIL, "Alert", text)

2. 限流(防刷屏)

python 复制代码
last_alert = {}

def alert_with_dedup(key, text, cooldown=300):
    if key in last_alert and time.time() - last_alert[key] < cooldown:
        return  # 5 分钟内同 key 不重发
    last_alert[key] = time.time()
    alert_slack(text)

3. 富文本(blocks 结构)

python 复制代码
alert_slack_blocks(
    f"排名变化",
    blocks=[
        {"type": "section", "text": {"type": "mrkdwn", "text": "*{{kw}}* 跌了"}},
        {"type": "section", "fields": [
            {"type": "mrkdwn", "text": f"上次: #{old}"},
            {"type": "mrkdwn", "text": f"这次: #{new}"}
        ]},
        {"type": "actions", "elements": [
            {"type": "button", "text": "查看详情", "url": url}
        ]}
    ]
)

4. 异步(不阻塞主流程)

python 复制代码
import threading

def alert_async(text):
    threading.Thread(target=alert_slack, args=(text,)).start()

5. 限速(Slack webhook 限速)

python 复制代码
# Slack webhook 限速 1 条/秒
import time

last_call = 0

def alert_rate_limited(text):
    global last_call
    now = time.time()
    if now - last_call < 1:
        time.sleep(1 - (now - last_call))
    last_call = time.time()
    alert_slack(text)

4 种方式实战代码

Slack

python 复制代码
import requests

SLACK_WEBHOOK = "https://hooks.slack.com/services/..."

def alert_slack_with_blocks(query, old_rank, new_rank, url):
    blocks = [
        {
            "type": "header",
            "text": {"type": "plain_text", "text": "📉 SERP 排名变化"}
        },
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": f"*{query}* 跌了 5 位以上"
            }
        },
        {
            "type": "section",
            "fields": [
                {"type": "mrkdwn", "text": f"上次: #{old_rank}"},
                {"type": "mrkdwn", "text": f"这次: #{new_rank}"}
            ]
        },
        {
            "type": "actions",
            "elements": [
                {"type": "button", "text": {"type": "plain_text", "text": "查看"}, "url": url}
            ]
        }
    ]
    requests.post(SLACK_WEBHOOK, json={"blocks": blocks}, timeout=5)

Email

python 复制代码
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

def alert_email_rich(to, query, old_rank, new_rank, url):
    msg = MIMEMultipart()
    msg["From"] = "alerts@yourdomain.com"
    msg["To"] = to
    msg["Subject"] = f"SERP Alert: {query} 变化"

    html = f"""
    <h2>SERP 排名变化</h2>
    <p>关键词: <b>{query}</b></p>
    <p>上次: #{old_rank} → 这次: #{new_rank}</p>
    <p><a href="{url}">查看 SERP 结果</a></p>
    """

    msg.attach(MIMEText(html, "html"))

    with smtplib.SMTP("smtp.gmail.com", 587) as s:
        s.starttls()
        s.login(USER, APP_PASS)
        s.send_message(msg)

Webhook(通用)

python 复制代码
import requests
import hmac
import hashlib

def alert_webhook_signed(url, payload, secret):
    body = json.dumps(payload)
    sig = hmac.new(secret.encode(), body.encode(), hashlib.sha256).hexdigest()

    headers = {
        "X-Signature": f"sha256={sig}",
        "Content-Type": "application/json",
    }

    for attempt in range(3):
        try:
            r = requests.post(url, data=body, headers=headers, timeout=5)
            if r.ok:
                return
        except Exception:
            time.sleep(2 ** attempt)

SMS

python 复制代码
from twilio.rest import Client

def alert_sms_emergency(to, query, new_rank):
    client = Client(TWILIO_SID, TWILIO_TOKEN)
    client.messages.create(
        from_="+1234567890",
        to=to,
        body=f"SEO: {query} 跌到 #{new_rank},立即查看!",
    )

实战数据(我项目 1 个月)

指标 数值
告警总次数 28 次
Slack 到达 28/28(100%)
Email 到达 24/25(96%)
Webhook 到达 28/28(100%)
SMS 到达 5/5(100%,仅用紧急)
平均延迟 Slack 2s
平均延迟 Email 60s
成本 Slack $0
成本 Email $0
成本 SMS $0.05(5 条紧急)

5 个最佳实践

  1. 多通道 fallback:Slack 主,Webhook 备,Email 三备,SMS 紧急
  2. 去重防刷屏:5 分钟同 key 不重发
  3. 限流防限速:Slack 1 秒/条
  4. 异步不阻塞:主流程触发告警就返
  5. 富文本优先:Slack 用 blocks,Email 用 HTML,展示清楚

小结

4 种告警方式选型:

  • Slack:团队用 Slack(90% 团队)
  • Email:非开发人员
  • Webhook:接自己系统
  • SMS:紧急高优(成本高,慎用)

serpbase + 任意告警方式,5 分钟搭好。serpbase 的 1.4s P50 + auto-refund 让你告警永远及时,失败不扣 credit。

相关推荐
高频因子挖掘机2 小时前
股票分红送转后价格“断层”:前复权、后复权和不复权该怎么选?
后端·github·api
用户298698530148 小时前
Python 实现 Word 转 XPS、PostScript 与 OFD 格式
后端·python·api
高频因子挖掘机11 小时前
量化回测为什么不能随便选前复权?从收益率计算到成交价格的三个误区
后端·github·api
高频因子挖掘机13 小时前
回测收益为什么可能不真实?从时间戳、数据可用性到未来函数检查
后端·github·api
高频因子挖掘机1 天前
只取最近 60 个交易日,却每次拉全历史:量化脚本变慢的原因与改法
后端·github·api
QuantiCore_IO1 天前
量化回测复权数据的工程实践:从 API 获取到数据质量验证
后端·github·api
高频因子挖掘机1 天前
Python 批量获取股票行情后,如何用 Pandas 统一字段、索引和数据类型?
后端·github·api
高频因子挖掘机1 天前
多股票 K 线如何用 Pandas 对齐?从收益率计算到横截面分析
后端·github·api
高频因子挖掘机2 天前
A股分钟K线数据占内存:先缩小请求范围,还是换 DataFrame 工具?
后端·github·api
高频因子挖掘机2 天前
量化研究中,为什么拿到 Pandas 行情数据不等于完成数据接入?
后端·github·api