⏰ 第08章 · Python 脚本自动化

贴吧签到/监控报告实践

Python 脚本自动化

这一章讲这台服务器上真实在跑的两种 Python 自动化脚本:贴吧签到(tieba_sign.py)和监控报告(monitor_report.py)。它们展示了"无浏览器"调用 HTTP 接口、读配置、处理数据、推送通知、被 cron 调度的完整套路。学会这套,你就能写自己的自动化脚本。

脚本模式概览

模式 说明 本机例子
读配置 从配置文件/环境变量取凭证 读 /root/.tieba_bduss、/root/.feishu_monitor.conf
无浏览器调接口 用标准库 urllib 发 HTTP 调贴吧 / 飞书接口
数据处理 解析 JSON、计算、生成图表 监控脚本用 matplotlib 画图
推送通知 HTTP 回调到聊天机器人 发飞书群消息
被调度 cron 每日执行 crontab -l 可见

为什么用标准库(urllib)而不是 requests

本机脚本特别强调"零依赖""无需浏览器",因为生产服务器尽量少装东西、少被网络限制绑架。Python 标准库 urllib.request/urllib.parse 足够发 GET/POST、带 header、处理 JSON。

import urllib.request, urllib.parse, json

# GET
with urllib.request.urlopen("https://example.com/api", timeout=10) as r:
    data = json.loads(r.read())

# POST JSON(带 header)
req = urllib.request.Request(
    "https://example.com/api",
    data=json.dumps({"k": "v"}).encode(),
    headers={"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=15) as r:
    resp = json.loads(r.read())

提示 | 有 requests 库会更顺手,但它不是标准库,需要 pip install。在"能少装就不装"的服务器/脚本里,urllib 是安全底座。必要时可用 venv 隔离装依赖。

贴吧签到脚本的要点

它用"BDUSS/STOKEN"这个登录凭证调贴吧客户端接口:

# 凭证两种放法:环境变量 或 配置文件(建议 chmod 600)
export TIEBA_BDUSS="..."
export TIEBA_STOKEN="..."
# 或写入
echo "你的BDUSS值" > /root/.tieba_bduss && chmod 600 /root/.tieba_bduss

关键逻辑:

def load_bduss():
    env = os.environ.get("TIEBA_BDUSS", "").strip()
    if env: return env
    # 从配置文件读
    try:
        with open("/root/.tieba_bduss") as f:
            return f.read().strip()
    except Exception:
        return ""

def http_json(url, bduss, stoken="", data=None):
    headers = {"User-Agent": "...", "Cookie": build_cookie(bduss, stoken)}
    req = urllib.request.Request(url, data=urllib.parse.urlencode(data).encode() if data else None,
                                 headers=headers)
    with urllib.request.urlopen(req, timeout=15) as r:
        return json.loads(r.read())

安全 | BDUSS/STOKEN 等同于账号钥匙。脚本用 chmod 600 保护凭证文件;不要把它写进版本库、不要打印到日志。

监控报告脚本的要点(macplotlib 画图 + 飞书推送)

它从 Prometheus 取时序数据、生成多面板仪表盘图片、上传到飞书:

import matplotlib
matplotlib.use("Agg")        # 无显示环境用 Agg 后端,必须放在 import pyplot 之前
import matplotlib.pyplot as plt

def query_range(server, query, start, end, step="60s"):
    p = urllib.parse.urlencode({"query": query, "start": start, "end": end, "step": step})
    with urllib.request.urlopen(f"{server}/api/v1/query_range?{p}", timeout=10) as r:
        return json.loads(r.read())
  • 注册中文字体:否则中文会变方块。代码里注册 Noto CJK / 文泉驿 / 微软雅黑等字体路径。
  • 生成图片:plt.savefig 到内存 io.BytesIO,再 base64 上传。
  • 飞书机器人:拿 app_id/app_secret 换 tenant_access_token,再调上传图片/发送卡片接口。
def get_token():      # 从配置读 app_id/app_secret,POST 换取 access_token
    data = json.dumps({"app_id": APP_ID, "app_secret": APP_SECRET}).encode()
    req = urllib.request.Request(TOKEN_URL, data=data, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req, timeout=10) as r:
        return json.loads(r.read())["tenant_access_token"]

def send_card(card):  # 发富文本卡片到群
    body = json.dumps({"msg_type": "interactive", "content": json.dumps(card)}).encode()
    req = urllib.request.Request(WEBHOOK, data=body,
                                 headers={"Content-Type": "application/json; charset=utf-8"})
    with urllib.request.urlopen(req, timeout=15) as r:
        return json.loads(r.read())

注意 | 飞书机器人有多种:自定义 Webhook 机器人 与 应用机器人。应用机器人需要 app_id/app_secret 换 token;自定义机器人只需一个 webhook 地址。按你的机器人类型选用对应的鉴权方式。

让脚本健壮的通用手法

手法 作用
timeout=15 调外部接口设超时,避免长时间挂住
用 try/except 捕获网络异常 失败时打日志,而不是让整个脚本崩掉
import logging 或 print 到日志 便于 cron 排查(重定向到日志文件)
配置集中放一个文件 本机读 /root/.feishu_monitor.conf,改配置不用改代码
凭证 chmod 600 安全
用 flock 防并发 避免两个实例互相干扰

相关命令

  • 手动调试:/usr/bin/python3 /root/scripts/tieba_sign.py
  • 加可执行权限:chmod +x
  • 看日志:tail -n 50 /var/log/tieba_sign.log
  • 定时执行:参考《定时任务实战》里的 crontab 写法。