多平台登录态巡检:cookie 判据为什么会撒谎

我们维护一套多平台发布链路,账号分散在十几个内容平台。每天开跑前都要回答同一个问题:哪个平台还能发,哪个已经掉了登录。

最初的巡检脚本很朴素------读一遍浏览器的 cookie,哪个平台的关键 cookie 在,就认为登录有效。跑了一周,结果和实际差得很远:说「已登录」的,打开后台是登录页;说「掉线」的,标签页里正好好登着。误报最严重那天,十几个平台错了五个。

坑一:cookie 存在不等于会话有效

三个实测反例,都发生在 cookie 名齐全的情况下:

  • 小红书:web_session 在,接口直接返回 401。
  • 公众号:账号被踢回登录页,但 slave_sid、slave_user、data_bizuin 一个都没被删。
  • 掘金:只有 passport_csrf_token、s_v_web_id 时,一堆 passport 前缀看起来像已登录,实际是未登录;真正的判据是 sessionid、sessionid_ss。

原因不复杂:退出登录时清 cookie 是前端行为,服务端会话失效不一定回写浏览器。所以 cookie 只能当初筛,它能筛掉「肯定没登过」的平台、省下开页面的时间,但不能拿它下「已登录」的结论。

坑二:判据要分三层

现在固定三层,成本逐层递增:

  1. cookie 初筛(毫秒级,不开页面):关键 cookie 一个都不在,直接判未登录。
  2. 落地 URL (打开后台首页,看最终地址):被 302 到 signin、login、passport 这类路径即未登录。
  3. 页面关键词(读 DOM 文本):首页出现「扫码」「重新登录」,或关键容器为空即未登录。

第二层能覆盖九成情况,第三层专治「SPA 空壳」------URL 没跳,页面却是白板,因为接口 401 后前端把 DOM 清空了。判据是 input 数为 0 且 body.innerText.length < 300;这时不要猜选择器,直接去问接口。平台自己有会话查询端点时,优先 fetch 它看 401,比读 DOM 稳。

坑三:备份键必须是三元组

巡检发现问题要能自动回灌,每个平台的登录态要落盘。第一版用 cookie 的 name 当键做差集,表现是:某些平台回灌后仍然掉登录,另一些回灌后多出一堆重复项。

原因是同名 cookie 可以并存------域名不同(a.com 与 .a.com)、路径不同(/ 与 /creator)都是不同的 cookie。只用 name 当键,后写的覆盖先写的,回灌时只补回其中一个。改成 (name, domain, path) 三元组后问题消失:

python 复制代码
def key(c):
    return (c["name"], c.get("domain", ""), c.get("path", "/"))

两条配套规则:备份用合并不覆盖,别整体覆写,否则一次异常态会把好备份冲掉;回灌只补「当前根本没有」的,不删不覆盖已有值------正在用的会话 cookie 被旧值覆盖,等于自己制造掉线。

坑四:浏览器级 CDP 只有 Storage.setCookies

Storage.setCookies、Storage.getCookies 在浏览器级连接上可用;而 Network.setCookie、Network.deleteCookies 属于页面会话,在 devtools/browser/<id> 这条 WebSocket 上调用会直接返回:

go 复制代码
-32601 Protocol error: 'Network.setCookie' wasn't found

这个错很容易被 try/except 吞掉,最后表现为「脚本没报错,cookie 却没进去」。所以回灌的回执必须回读:把发出去的 cookie 逐个 (name, domain, path) 与 Storage.getCookies 的结果比一次,缺一个都算这次回灌失败。

坑五:cron 的解释器不是你以为的那个

巡检是定时跑的。系统 python3 是 3.6,项目 venv 是 3.11。cron 里写 python3 script.py,缺 websocket-client 直接崩,日志只有一行 ModuleNotFoundError,看板上就变成「全部平台未登录」。修法是脚本顶部自检,缺包就 os.execv 换到 venv 解释器,一行判断省掉一整类误报。

顺带一点:cron 的 PATH 常缺 /usr/local/bin,脚本里自己设一遍,别指望环境。

巡检结果长什么样

每次落一行 JSON:{"platform":"juejin","at":"2026-11-10T20:10:00+08:00","cookie":true,"url_ok":true,"dom_ok":true,"status":"active","cost_ms":2140}。

status 只有三档:active(三层全过)、expired(任一层明确判否)、unknown(超时或打不开)。unknown 不许当 active 用 ------超时被当登录有效,正是最初误报的一半来源。发布任务的前置条件就一句:status == "active" 才开跑;加上之后,失败类型从「发到一半发现没登录」变成「开工前就知道要扫码」。

小结

五个坑一个共性:判据给的往往是「看起来对」,不是「确实对」。

  • cookie 存在 ≠ 会话有效
  • URL 没跳 ≠ 页面加载成功
  • 回灌返回成功 ≠ cookie 落进去了
  • 巡检说已登录 ≠ 能发文

所以每条判断都要回读校验,并把「说不准」单独落一档。自动化的难点不在把动作做出来,而在不确定时敢说「我不知道」。

相关推荐
量化分析码农1 小时前
【Python量化趋势跟踪实战 01】均线多头排列就是趋势开始吗:过滤与确认
python
用户298698530141 小时前
Python 实战:把代码写入 Word 文档的两种实现方式
后端·python·api
小小张说故事1 小时前
Python 里 pickle 到底存了什么:拆开 __reduce__、__getstate__ 和那串能执行代码的字节码
python
reasonsummer1 小时前
【教学类-150-03】20261108蝴蝶连连看html(一页2个版面、3个版面)
python·html
用户019027581612 小时前
用 Polars 快速分析 A 股 K 线:比 pandas 更快的列式处理
python
用户0332126663672 小时前
使用 Python 轻松加密或解密 Excel 文档
python·excel
CyrusYiVPP3 小时前
手写 MCP Server:给问答机器人接上本地文件工具,Python 实战第 13 期
人工智能·python
特立独行的猫A3 小时前
cj-tauri:用仓颉写桌面与鸿蒙 PC 应用
java·后端·python
qq_1588954111112 小时前
AI 音乐生成完成后,音频 URL 为什么会过期?一套可恢复的交付方案
python·api·ai音乐