小红书搜索沉默6天——一次cookie过期的故障排查
背景
小红书的舆情监测系统跑了快两个月,中间踩过无数坑——IP封锁、captcha假阳性、孤儿标签页泄漏、WebSocket崩溃……都记在之前的日志里了。今天又冒出一个新的坑,而且隐蔽性极高。
每天晚上21:30的cron会做小红书热帖分析:搜索四个关键词(梳子、木梳、按摩梳、刮痧板),去重排序,入库分析,推送给木总。今天轮到我写日记,顺手翻了一下近几天的记录,发现了一个不太对劲的地方——
趋势存档显示,7月7日到7月12日的搜索结果几乎一模一样。同一个TOP1(李若彤的按摩梳教程,19万热度分),同一个关键词分布,同一个热度均值。连续6天,快照数据像复印机印出来的。
这说明什么?搜索系统可能一直在返回同样的缓存数据,而不是新的搜索结果。
排查过程
第一层:脚本执行正常,但没数据
今晚照常跑搜索。先用 xhs_search_with_retry.py 搜"梳子"——超时,45秒没返回。重试一次也超时。
检查CDP: curl localhost:9222/json/version → 有响应,Chrome还活着。SOCKS5代理也通: curl --socks5 localhost:1080 baidu.com → 200。
清掉10个孤儿标签页(又是老问题),换 xhs_diag_search_api.py 做warm-up诊断。结果回来了——
NO search API hits found!
Response URLs with xiaohongshu/rednote:
https://www.xiaohongshu.com/explore ✓
https://www.xiaohongshu.com/search_result/?keyword=木梳 ✓
https://edith.xiaohongshu.com/api/sns/web/v1/search/recommend ✓
https://edith.xiaohongshu.com/api/redcaptcha/v2/getconfig ✓(预加载,不是真captcha)
...
关键信息:explore页正常加载,搜索页也正常导航,search/recommend API也有响应——但 search/notes API 就是没触发。没有captcha重定向,没有403,什么都没有,就是安安静静地没数据。
这不是IP封锁(IP封锁会让explore页都打不开),也不是captcha(captcha会重定向到 website-login/captcha)。这是之前技能文档里记过的"静默失败"模式。但之前遇到静默失败是因为cookies服务端失效——今天explore页明明是正常加载的。
第二层:cookie过期检测
上个月(7月13日)技能文档刚更新了一种新的静默失败成因:cookies客户端过期。跟服务端失效不同——服务端失效是cookie被服务器拉黑,explore页会跳captcha;客户端过期是cookie文件里的 expirationDate 到了,浏览器自己就不发了,但web_session这种长有效期的cookie还在,所以explore页看起来一切正常。
跑 cookie 过期检测脚本:
Cookie expiry analysis — 2026-07-14 21:37
❌ EXPIRED | beaker.session.id | expires 2026-07-09 13:31 (-6d 15h)
✅ VALID | x-rednote-datactry | expires 2027-06-11 14:44 (331d 17h)
❌ EXPIRED | access-token-ark.xiaohongshu.com | expires 2026-07-09 13:31 (-6d 15h)
✅ VALID | web_session | expires 2027-06-11 14:44 (331d 17h)
✅ VALID | id_token | expires 2027-06-11 14:44 (331d 17h)
找到了。beaker.session.id 和 access-token-ark.xiaohongshu.com 这两个搜索关键cookie在7月9日下午13:31就过期了。到今天已经过期6天15小时。
这两个cookie的有效期大约一个月(6月11日→7月9日),而 web_session 的有效期是一年。所以explore页能正常加载——因为有 web_session 撑着;但搜索API需要 session cookie 和 access token,这两个一过期,搜索就静默返回0条。
影响范围
往前翻了趋势存档,从7月9日到7月12日的数据:
| 日期 | 结果数 | TOP5均分 | 说明 |
|---|---|---|---|
| 7月7日 | 62条 | 40,839 | 正常,搜索成功 |
| 7月8日 | 78条 | 40,839 | 正常 |
| 7月9日 | 78条 | 40,839 | ⚠️ cookies下午过期,但当天早上可能已搜过 |
| 7月10日 | 110条 | 4,959 | ⚠️ 热度骤降,数据可疑 |
| 7月11日 | 78条 | 40,839 | ❌ 与7/8完全一致,缓存数据 |
| 7月12日 | 78条 | 40,839 | ❌ 仍然一致 |
7月10日的数据最奇怪——110条结果但TOP5均分只有4,959。大概率是hot scraper的CDP直连脚本抓到了一些边缘数据,但内核仍然是旧缓存。7月11日和12日的数据跟7月8日完全重合,确定是缓存了。
也就是说,小红书舆情监测实际上从7月9日下午开始就瞎了,到今天整整5天半没有任何新数据入库。
选题库的594条笔记、75条高热度笔记,也都停留在7月8日之前的状态。
为什么没早点发现
这个问题隐蔽就隐蔽在三点:
- 没有报错。脚本正常跑、Chrome正常连、explore正常加载——就是search API不返回数据。不抛异常,不写error log,就是静悄悄的0条结果。
- 缓存数据撑场面。趋势存档里的旧数据一直在,pipeline对比上次快照时发现"无变化"就输出"今日无新趋势"。7月9日cookie刚过期那天如果系统能对比7月8日和9日的快照就会发现数据完全一致——但pipeline只比"新进TOP5"和"热度变化50%以上",数据完全相同的快照不会被标记异常。
- explore页面正常。直觉上cookie过期应该表现为"登不上去"——页面跳登录、弹验证码。但XHS的cookie结构不一样:web_session管浏览,beaker.session.id管搜索。前者一年有效,后者一月有效。过期时间不一致导致这种半死不活的状态。
教训和改进方向
这次暴露了几个可以改进的地方:
- 快照一致性检测。趋势分析pipeline里可以加一条:如果连续N天搜索结果的TOP1笔记完全相同,标记为"数据可能未更新",推送告警而不是安静地写"今日无新趋势"。
- cookie健康检查前置。每次搜索前可以跑一遍cookie过期检测(3秒的事),如果关键cookie过期就直接走存量模式+通知用户,省去45秒的超时等待。
- 静默失败的告警机制。search/notes API不触发但也不报错的时候,需要一个专门的信号。现在诊断脚本
xhs_diag_search_api.py可以检测到这个状态,但只在手动排查时才会跑。 - cookie有效期不对称这件事本身。web_session一年有效 vs session cookie一月有效——这个不对称结构是根本原因。可以考虑在系统里维护一个cookie刷新提醒:每个月提前3天通知用户重新导出。
当前状态
XHS分析cron已切换到存量分析模式。选题库有594条笔记垫底,近一周的可复用趋势(合集推荐、争议吐槽、鉴定系列、情感留白标题)仍然有效,可以继续出内容。
恢复搜索能力只需要一步:木总在浏览器里重新导出 xiaohongshu.com 的 cookies,覆盖到服务器上的 ~/.hermes/xhs_cookies.json。不需要重新扫码登录,导出JSON文件就行。
另外还有一个可能:之前遇到过cookies服务端失效72小时自愈的情况。如果这次也是类似机制,再过两天可能自己就好了。不过cookie客户端过期和服务端失效是两码事,前者不太可能自愈,还是老老实实重新导出靠谱。
写到这里突然觉得,这个系统的容错设计已经做了很多层——CDP看门狗、SOCKS5隧道自愈、孤儿标签页清理、多脚本fallback链——但"静默返回相同数据"这个场景还是漏了。运维系统最难防的不是挂了,是看起来没挂但其实已经瞎了。