微博超话自动签到系统:云函数实现,附 Cookie 7 天失效问题的分析与解决

发布时间:2026/7/11 4:36:06
微博超话自动签到系统:云函数实现,附 Cookie 7 天失效问题的分析与解决 用 Python 云函数实现的微博超话自动签到系统每天定时给所有关注的超话签到结果邮件通知全程无人工介入。本文介绍系统架构并重点分析运行中遇到的「Cookie 每 7 天失效」问题的原因与解决方案。代码已开源。GitHub微博超话自动签到运行效果——每天 09:00 云端定时触发24 个关注的超话逐个自动签到Cloud Logging 日志每行为一个超话的签到记录名称、id、状态、返回消息最后一行为当日汇总签到完成共 24 个成功 24失败 0。一、系统架构流程分为本地和云端两部分本地一次性Playwright 打开浏览器扫码登录 → 获取全部域的 Cookie → 上传云端存储 云端每日自动 Cloud Scheduler 定时触发 Cloud Functions → 读取 Cookie 并验证有效性无效则邮件告警 → 调微博 API 获取关注的超话列表自动翻页 → 逐个发送签到请求随机延迟 3–8 秒 → 签到结果写入日志、发送每日汇总邮件技术栈Python 3.11、Playwright仅本地登录用、GCP Cloud Functions Cloud Scheduler Cloud Storage、Gmail SMTP。几个设计要点微博网页端不支持账号密码直接登录脚本化用 Playwright 真浏览器扫码登录登录过程中的跨域 Cookie 交换由页面 JavaScript 完成纯 API 方式拿不到完整 Cookie这是引入 Playwright 的原因超话列表从 API 动态获取并自动翻页不写死签到请求带浏览器 headers、请求间随机延迟降低被风控识别的概率二、问题Cookie 每 7 天失效系统上线后遇到的主要问题6 月 11 日登录获取的 Cookie6 月 18 日失效正好 7 天。失效后需要重新手动扫码与全自动的目标不符。三、排查先确认 Cookie 本身的有效期第一个假设Cookie 的expires属性本身就是 7 天。验证方式Playwright 的context.cookies()返回每个 Cookie 的expires时间戳我最初的代码只保存了 name/value/domain把这个字段丢掉了。补上记录逻辑后重新登录实测结果登录日期 7 月 8 日关键 Cookie 过期时间 SUB (.weibo.com) → 2027-07-08 一年 SUBP (.weibo.com) → 2027-07-08 一年 ALF (.weibo.com) → 2026-08-07 30 天 SUBP (.sina.com.cn) → 2026-07-15 7 天 SSOLoginState (.weibo.cn) → session cookie假设不成立签到所依赖的主力 Cookie.weibo.com 的 SUB账面有效期是一年但实际 7 天就失效了。四、原因分析失效的是服务端 Session不是 Cookie这里需要区分两个概念。HTTP 是无状态协议登录态由 Cookie 和 Session 配合维持CookieSession存放位置客户端浏览器服务端内容凭证字符串如SUB_2A25Eb...该凭证对应的用户、状态、有效期Cookie 只是凭证的载体凭证是否有效由服务端的 Session 记录决定。Cookie 的expires只约束浏览器何时删除它不代表服务端认它多久。所以现象的解释是Cookie 没过期是微博服务端把这个凭证对应的 Session 作废了。进一步的问题是普通用户天天用浏览器刷微博同样的机制为什么不会 7 天被登出对照浏览器的标准行为和几个同类开源项目的实现差异在于正常浏览器日常请求中服务器会通过Set-Cookie响应头不定期换发新凭证浏览器自动收下并替换旧值服务端同步更新 Session、有效期重新起算。登录态是一条持续传递的链每一环都重新计时我的脚本登录当天保存了一份 Cookie 快照之后每天原样重放。服务器换发的新 Cookie 随着脚本进程退出全部丢失服务端的 Session 从未得到更新一个签发后从不更新的凭证7 天被服务端作废——这个阈值大概率就是微博对长期无更新 Session的清理策略。五、解决方案把换发的新 Cookie 写回存储方案每天签到执行完毕后收集本次运行期间服务器通过 Set-Cookie 下发的新 Cookie合并写回持久化存储次日使用更新后的版本。requests库会自动把响应中的 Set-Cookie 存入session.cookies只是脚本退出后丢失。需要做的是在退出前持久化以下为简化版完整实现见文末仓库defpersist_refreshed_cookies()-list[str]:把本次运行期间服务器通过 Set-Cookie 换发的新 Cookie 合并写回存储refreshedlist(SESSION.cookies)list(weibo_api.SESSION.cookies)dataload_stored_cookies()# 读取当前存储的 cookie 列表index{(c[name],c[domain].lstrip(.)):cforcindata}changed[]forcinrefreshed:key(c.name,(c.domainor).lstrip(.))entryindex.get(key)ifentryisNone:# 服务器下发了新增的 cookiedata.append({name:c.name,value:c.value,domain:c.domain})changed.append(c.name)elifentry[value]!c.value:# 服务器轮换了已有 cookie 的值entry[value]c.value changed.append(c.name)ifchanged:save_stored_cookies(data)# 写回持久化存储returnchanged实现细节按 (name, domain) 匹配而不是只按 name同一个SUB在.weibo.com、.weibo.cn、.sina.com.cn下各有一份Cookie 域隔离不能互相覆盖只在有实际变化时写回并在日志中记录更新了哪些 Cookie便于确认机制是否在工作写回步骤用 try/except 包裹失败降级为警告不影响当次签到结果六、延伸SSO 登录中心与 ALC调研同类项目时发现浏览器维持登录态实际有两层机制第一层换发SUB 有效期间日常请求中 Set-Cookie 轮换Session 持续续期 第二层重签SUB 失效后凭 ALC 向 SSO 登录中心直接换取新的 SUB不需要重新登录 两层都失效 → 才需要真正的重新扫码/输密码微博/新浪各站点共用 SSO 登录中心login.sina.com.cn。登录成功时登录中心会在自己的域下发长效凭证ALC社区经验有效期以月计。SUB 过期后携带 ALC 访问 SSO 端点即可换取新的 SUB——浏览器的静默续登走的就是这条路。值得注意的是用 Playwright 走完整登录流程时context.cookies()会带出所有域的 CookieALC 已经包含在内只是容易被当成无用杂项。开源项目 WeiboTask 即采用纯 ALC 方案——每次任务用 ALC 现换新 SUB不维护 SUB 的生命周期。七、社区同类方案对比脚本如何维持微博登录态在社区里有五类解法方案思路局限静态重放抓一次 Cookie 反复使用7 天失效续期回写本文每天把 Set-Cookie 写回存储链条中断后仍需重新扫码ALC 重签WeiboTask持有 SSO 长效凭证随用随换 SUBALC 也会过期数月获取需手动操作MITM 抓取Surge/QuantumultX手机代理拦截真实请求提取 Cookie付费 App、需装证书浏览器同步CDP常驻 Chrome 维持登录态脚本定期读取其 Cookie依赖该机器和浏览器持续运行较完整的做法是续期回写 ALC 重签两层结合行为与真实浏览器一致。八、当前状态与后续续期机制已于 7 月 8 日部署上线文章开头的日志为上线后第 2 天的运行记录。两个验证节点7 月 15 日第 7 天若签到仍正常说明换发链有效7 天失效问题解决8 月 7 日第 30 天ALF 的账面到期日验证换发是否连同长效凭证一起延期结果出来后会更新本文。若续期机制不足以解决下一步计划实现 ALC 重签作为第二层保障。另外一个调研中的发现微博会校验登录 IP 归属地。云函数部署在与本人常用 IP 相近的 region本文用 asia-east1未触发风控但社区反馈用 GitHub Actions美国机房 IP运行会出现异地登录异常。选择云端方案时需要注意。完整代码已开源含 Cloud Functions 部署配置、Playwright 扫码登录、邮件通知GitHubhttps://github.com/200-design/Weibo-Super-Topic-Auto-Check-in如果本文对你理解 Cookie/Session 机制有帮助或你也在做类似的自动化欢迎点个 Star ⭐。有问题评论区见。