资讯动态

微信公众号天气推送实战:定时任务+模板消息+天气API全链路

发布时间:2026/10/21 14:47:08 来源:尧图企业网站定制
简介这是一份面向零基础或略有编程经验用户的微信公众号天气推送制作资源核心解决如何为伴侣定时发送每日天气与纪念日提醒的问题支持在GitHub上每日自动线上运行。资源包共5个文件包含py主程序、yml工作流配置、txt配置与说明、md文档等压缩包仅5KB轻量易部署需自行申请天行、和风等天气API。内容覆盖最新完整版、简化版、星座版、星座加天气版及PHP版本附带成品、源码与消息模板方便按需选用。已有7695人学习下载说明该方案在情侣互动场景中接受度较高。读者可从中获得可直接运行的推送脚本、GitHub Actions自动执行配置、消息模板与多版本对照思路既能快速搭建属于自己的天气通知公众号也能借此理解定时任务与接口调用的基本流程适合想用低成本方式制造日常惊喜的开发者尝试。1. 从一条“今天记得带伞”开始公众号天气推送到底怎么跑通有个做后端的朋友女朋友嫌他每天只会发“早安”他干脆花了一个周末用微信公众号做了个每天定时推送天气的小工具。上线第一周女朋友觉得挺新鲜第二周开始她出门前会先看一眼推送里的降温和降雨提醒。这件事的技术含量其实不高但它把“微信公众号 天气通知”这条链路完整跑通了定时任务触发、第三方天气接口拉数据、模板消息组装、调用微信接口下发。整套东西一台最便宜的云服务器就能跑成本几乎为零。这份教程适合三类人一是想练手微信公众号开发、但不知道做什么练手项目的新手二是想给身边人做点实用小工具的开发者三是已经会写代码但没接触过微信模板消息、订阅通知、定时任务调度的熟手。它不涉及复杂算法难点全在“配置对不对、参数有没有过期、接口返回码看不看得懂”这些琐碎地方。下面按“先搞清楚原理再动手复现最后避开坑”的顺序拆开讲。2. 把链路拆开公众号、天气接口、定时任务各管什么2.1 三个角色和一次推送的完整生命周期先建立一个心智模型。整个系统里有三个角色微信公众号消息出口、天气数据源消息内容、你的服务器调度中枢。一次推送的生命周期是这样的服务器上的定时任务在每天早上 7 点被唤醒它拿着预先配置好的城市编码去请求天气接口拿到 JSON 数据后解析出温度、天气现象、风力、降雨概率再按模板格式拼成一段文本最后调用微信的接口把这段文本推给指定用户。这里有个关键认知公众号本身不会主动去查天气它只是一个消息通道。所有逻辑都在你自己的服务器上。所以“推送天气”这件事本质是“你的程序定时跑一次把结果通过微信的通道发出去”。理解这一点后面所有配置就都顺了。微信这边目前主流有两种下发方式模板消息和订阅通知。模板消息适合服务号用户关注后即可长期接收订阅通知适合订阅号需要用户每次授权一次或多次。个人做给女朋友用通常用测试号或服务号走模板消息最省事因为测试号不需要认证就能拿到模板消息权限调试阶段非常友好。2.2 天气数据源怎么选免费接口的字段与限制天气接口的选择直接决定你后面解析代码怎么写。常见做法是选一家提供免费额度的天气 API重点看三个东西是否支持城市编码/经纬度查询、返回字段是否包含未来天气和降雨概率、免费调用次数够不够每天一次。以常见的返回结构为例核心字段一般长这样字段名含义用途city / location城市名推送开头显示temp / temperature当前温度正文核心数据text / weather天气现象晴/雨/阴humidity湿度可选展示windScale / wind风力可选展示forecast未来几天预报做“明天降温”提醒选接口时有个血泪经验别只看文档写的字段名一定要用 curl 实际请求一次看真实返回。很多接口文档和实际返回的字段名对不上或者免费版砍掉了 forecast 字段。先跑通一次真实请求再写解析代码能省掉大量返工。提示免费天气接口通常有 QPS 限制和每日调用上限。个人使用每天一次完全够但如果你打算给多个人推送记得把结果缓存下来复用别每个人查一次。2.3 定时任务cron 表达式与调度方式定时任务负责“每天几点触发”。最轻量的做法是在服务器上写一个 Python 脚本用系统自带的 cron 调度。cron 表达式五个字段分别是分、时、日、月、周。比如每天早上 7 点整触发# 编辑当前用户的定时任务 crontab -e # 每天早上 7:00 执行推送脚本日志追加到 push.log 0 7 * * * /usr/bin/python3 /home/user/weather_push.py /home/user/push.log 21这段配置的含义0 7 * * *表示每天 7 点 0 分执行后面是脚本的绝对路径必须用绝对路径因为 cron 的环境变量和你登录 shell 的环境变量不一样用相对路径或依赖 PATH 经常会找不到命令 push.log 21把标准输出和错误都写进日志方便排查。如果你不想用 cron也可以用 Python 的schedule库或APScheduler在脚本内部循环调度。区别是cron 由系统托管脚本崩了下次照样触发内部调度需要脚本常驻进程挂了就全停了。个人项目推荐 cron简单可靠。3. 动手复现从测试号配置到推送脚本落地3.1 拿到 appID、appsecret 和用户 openid动手第一步是把微信侧的三个关键凭证拿到手appID、appsecret、用户 openid。用测试号的话登录测试号管理页面就能看到 appID 和 appsecret。openid 是每个用户对每个公众号唯一的标识你需要让女朋友先关注这个测试号然后通过“接收消息”或“获取用户列表”接口拿到她的 openid。获取 access_token 是所有微信接口调用的前置步骤它相当于调用凭证有效期通常 7200 秒过期要重新获取。所以脚本里不能写死每次运行前先换一个新的import requests APPID 你的appID APPSECRET 你的appsecret def get_access_token(): 获取微信接口调用凭证有效期约2小时 url https://api.weixin.qq.com/cgi-bin/token params { grant_type: client_credential, appid: APPID, secret: APPSECRET } resp requests.get(url, paramsparams, timeout10) data resp.json() # 返回码 0 表示成功其他值要打印出来排查 if data.get(errcode): raise RuntimeError(f获取token失败: {data}) return data[access_token]逻辑说明grant_type固定填client_credentialappid和secret从配置读取。参数说明timeout10防止请求卡死判断errcode是因为微信失败时不一定返回 HTTP 错误码而是返回一个带errcode的 JSON不判断就会拿到一个空 token 继续往下跑最后报一个看不懂的错。注意appsecret 泄露等于别人可以冒充你的公众号发消息。别把它硬编码进要上传到公开仓库的代码里用环境变量或单独的配置文件并且把配置文件加进.gitignore。3.2 拉取天气并组装模板消息拿到 token 后先请求天气接口再把数据填进模板。模板消息的data字段是一个键值对结构每个键对应模板里定义的一个占位符。假设模板里定义了city、date、weather、temp、tip五个字段import requests from datetime import datetime def get_weather(city_code): 请求天气接口返回解析后的字典 url https://api.example-weather.com/v1/current params {city: city_code, key: 你的天气接口key} resp requests.get(url, paramsparams, timeout10) raw resp.json() # 按真实返回结构取值字段名以实际请求结果为准 return { city: raw[data][city], weather: raw[data][text], temp: raw[data][temp], humidity: raw[data][humidity] } def build_message(openid, weather): 组装模板消息体 today datetime.now().strftime(%Y年%m月%d日) tip 今天有雨记得带伞 if 雨 in weather[weather] else 今天天气不错放心出门 return { touser: openid, template_id: 你的模板ID, data: { city: {value: weather[city]}, date: {value: today}, weather: {value: weather[weather]}, temp: {value: f{weather[temp]}℃}, tip: {value: tip} } }逻辑说明get_weather负责把接口原始返回整理成干净字典隔离字段名变化build_message负责拼装tip用简单的关键词判断生成一句人话。参数说明touser是接收者的 openidtemplate_id是你在公众号后台选定的模板 IDdata里每个字段的value必须是字符串传数字有时会报格式错误。3.3 调用下发接口并处理返回码最后一步是把组装好的消息 POST 给微信的模板消息接口def send_message(access_token, message): 下发模板消息返回微信的响应 url fhttps://api.weixin.qq.com/cgi-bin/message/template/send?access_token{access_token} resp requests.post(url, jsonmessage, timeout10) result resp.json() # 40001 通常是 token 失效40037 是模板ID错误 if result.get(errcode) ! 0: print(f下发失败: {result}) else: print(下发成功) return result if __name__ __main__: token get_access_token() weather get_weather(101010100) msg build_message(女朋友的openid, weather) send_message(token, msg)逻辑说明token 拼在 URL 上消息体用json传。参数说明errcode为 0 才算成功常见错误码里40001表示 token 无效多半是过期或 appsecret 错40037表示 template_id 不对43004表示用户没关注或 openid 不对。把返回码打印出来排查效率会高很多。4. 避坑与排查那些让推送“玄学失败”的细节4.1 现象本地跑得好好的服务器上不推送原因cron 执行时的环境和你手动执行时不同最常见的是 Python 路径不对、依赖库没装在系统 Python 里、或者脚本里用了相对路径读配置文件。解决cron 里用绝对路径调用 Python 和脚本在脚本开头把工作目录切到脚本所在目录或者所有文件路径都写绝对路径用which python3确认解释器路径。日志里如果出现ModuleNotFoundError说明依赖装在了虚拟环境而 cron 用的是系统 Python改成虚拟环境里的解释器路径即可。4.2 现象接口返回 40001token 明明刚获取原因access_token 是全局唯一的如果你在别的地方比如另一个脚本或调试工具也调用了获取 token 的接口新 token 会把旧的顶掉导致你手里的 token 瞬间失效。解决全项目只保留一个获取 token 的入口拿到后缓存起来比如写进文件或内存在有效期内复用。调试时别反复手动调 token 接口。4.3 现象模板消息报 40037 或提示字段不匹配原因template_id 填错或者data里的键名和模板定义的占位符对不上。模板里叫weather你传了weatherText就会报错。解决去公众号后台把模板内容复制出来逐个核对占位符名称大小写敏感。改完模板后 template_id 可能变化要同步更新配置。4.4 现象推送成功但内容全是空白或乱码原因天气接口返回的字段名和代码里取的不一致取到了空值或者编码没处理好。解决在get_weather里先把raw完整打印一次对照真实字段名改取值路径。中文乱码一般是响应头编码问题requests通常能自动处理如果不行手动指定resp.encoding utf-8。4.5 现象某天突然不推了日志也没报错原因免费天气接口额度用尽、key 过期或者微信侧模板被下架。这类问题不会抛异常只是返回空数据或错误码。解决在脚本里对关键返回值做校验天气数据为空时主动打印告警给 cron 加一个“心跳”机制比如每天推送成功后往日志写一行带日期的记录隔天扫一眼就知道有没有断。5. 进阶玩法让推送更“像人发的”几个技巧跑通基础版之后真正拉开体验差距的是内容组织。我一般会做三件事。第一加一句基于天气的个性化提醒温度低于 5℃ 提醒穿厚外套降雨概率高于 60% 提醒带伞温差超过 8℃ 提醒添衣。判断逻辑就是几个 if但读起来完全不一样。第二把未来一天的预报也带上比如“明天降温 6℃记得加衣”这需要天气接口支持 forecast 字段取forecast[1]的数据和今天对比即可。第三控制推送时间别设太早7 点到 7 点半之间比较合适太早打扰休息太晚出门前看不到。验证推送是否正常我习惯用一个“干跑”模式在脚本里加一个DRY_RUN开关打开时只打印组装好的消息内容不真正调用下发接口。这样调试模板格式时不会因为频繁调用触发频率限制也不会给女朋友发一堆测试消息。DRY_RUN True # 调试时打开只打印不发送 if __name__ __main__: token get_access_token() weather get_weather(101010100) msg build_message(女朋友的openid, weather) if DRY_RUN: print(预览消息:, msg) else: send_message(token, msg)这个开关看着简单但能省掉很多“手滑发出去”的后悔药。从那以后我每次改模板格式都强制先走一遍DRY_RUN确认文案和字段没问题再关掉。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑