🐂🐎 牛马专列 – 第三辑:7日天气趋势卡片 + 每日星期提醒(含飞书图片上传链路)
第二辑之后,我把牛马专列继续往“更像一个可长期运行的小系统”推进了一步。
这次核心不是再加几条文案,而是把卡片能力做完整:支持图片上传、行内温度条、星期主题提醒、配置统一和主流程接入。
代码地址:https://github.com/rainding0311/lark_webhook_reminder/tree/main
本次新增能力
- 墨迹天气 7 日趋势卡片(行内温度条图片版)
- 每日星期提醒(周一到周五文案 + assets 配图)
- 飞书图片上传链路打通(本地图片 -> image_key -> 卡片 img)
- 配置统一(webhook 多群、墨迹参数、飞书应用参数)
- 主流程定时接入(天气提醒后 5 分钟发送新卡片)
新功能一:墨迹天气 7 日趋势卡片
相比第二辑只发“今日/明日天气”,这版新增了 7 天卡片,核心点是:
- 数据源改为墨迹接口(15 天接口里取前 7 天)
- 卡片展示“日期 / 天气 / 低温 / 温度条 / 高温”
- 温度条采用图片方式渲染(支持渐变、圆角、中点)
- 卡片底部注明数据来源

主流程触发时间:
- 08:35(晚于 08:30 天气提醒 5 分钟)
- 18:05(晚于 18:00 天气提醒 5 分钟)
新功能二:每日星期提醒(周一到周五)
新增了 weekday_theme_reminder(),按工作日自动选择文案和配图:
- 周一到周五固定三段文案
- 配图来自 assets/monday.jpg … friday.jpg
- 图片上传失败时自动回退为纯文字卡片(不中断发送)
示例文案(周五):
- 周五不加班,快乐很简单。
- 今日任务:准时下班,拒绝内卷。
- 周五到,烦恼跑,快乐马上到。

默认触发时间:
- 09:05(可在配置中调整)
关键实现:飞书图片上传链路
很多人一开始会以为 webhook 可以直接发本地文件。实际上不行。
正确链路是:
- 用 app_id/app_secret 换 tenant_access_token
- 调用图片上传接口,把本地图片传到飞书,拿到 image_key
- 在消息卡片里通过 img_key 引用图片
1) 获取 token
resp = requests.post(
"https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
headers={"Content-Type": "application/json"},
data=json.dumps({"app_id": app_id, "app_secret": app_secret}),
timeout=8
)
tenant_access_token = resp.json()["tenant_access_token"]
2) 上传图片
files = {"image": ("friday.jpg", open(image_path, "rb"), "image/jpeg")}
data = {"image_type": "message"}
resp = requests.post(
"https://open.feishu.cn/open-apis/im/v1/images",
headers={"Authorization": f"Bearer {tenant_access_token}"},
data=data,
files=files,
timeout=12
)
image_key = resp.json()["data"]["image_key"]
3) 卡片引用图片
{
"tag": "img",
"img_key": image_key,
"alt": {"tag": "plain_text", "content": "周五提醒配图"},
"custom_width": 260
}
配置统一
这版把配置收敛到了 reminder_config.json,主流程和测试脚本都读同一套配置。
{
"webhook_urls": [
"https://open.feishu.cn/open-apis/bot/v2/hook/xxx1",
"https://open.feishu.cn/open-apis/bot/v2/hook/xxx2"
],
"moji_weather": {
"id": "10007609",
"key": "your-moji-key",
"sheng": "上海",
"place": "上海市",
"days": 7,
"style": "apple"
},
"feishu_app": {
"app_id": "cli_xxx",
"app_secret": "xxx"
},
"weekday_reminder": {
"enabled": true,
"time": "09:05"
}
}
定时点总览(工作日)
| 时间 | 内容 |
|---|---|
| 08:30 | 今日天气提醒 |
| 08:35 | 墨迹 7 日天气趋势卡片 |
| 09:05 | 星期提醒卡片(周一到周五) |
| 10:50 | 午餐提醒(按钮卡片) |
| 13:00 / 15:00 / 17:00 | 下班倒计时 |
| 17:50 | 下班前提醒 |
| 18:00 | 明日天气提醒 |
| 18:05 | 墨迹 7 日天气趋势卡片 |
单次测试脚本
这次也补了三个 once 脚本,方便你每次改完先验效果:
- moji_weather_once.py:单次发 7 日天气卡片
- weekday_reminder_once.py:单次发星期提醒
- feishu_image_once.py:单次测试图片上传链路
运行方式
pip install requests apt-get install -y python3-pil nohup python3 work_reminder_v3.py > nohup.out 2>&1 &
这版踩过的坑
- 双发消息:不是 webhook 重复,是两台服务器同时跑了进程。
- 锁文件失效:相对路径锁文件在不同启动目录会失效,已改为脚本绝对路径。
- Pillow 未安装:会导致图片温度条不可用,已做自动降级到文本温度条。
- 多行命令参数报错:\ 后面有空格会让 shell 断行失败。
小结
第三辑的重点是把“提醒”做成“可维护的卡片系统”:
- 体验层:天气趋势和星期提醒更完整
- 技术层:飞书图片上传链路打通
- 工程层:配置统一、主流程接入、故障降级完善