xueqiu: 匿名 token 可从 /hq 取得,首页兜底已失效导致 400016;过期的 xueqiu_cookie 还会静默屏蔽兜底

Author: terrytao1988Created Sep 1, 2026Updated Sep 1, 2026

概要

v1.5.0 的 xueqiu channel 在我机器上稳定报 HTTP Error 400error_code: 400016)。排查下来有两个独立的 bug,都不需要真实登录态就能修复——匿名 token 是拿得到的,只是取 token 的页面选错了

这条与已关闭的 #219 结论相反:#219 的修复方向是「必须复用浏览器登录 cookie」,但实际上公开行情接口只要一个匿名 xq_a_token 就够。

环境:Agent Reach v1.5.0,WSL2 (Ubuntu),Python 3.14,无代理。


Bug 1:_XUEQIU_HOME 指向的首页已不再下发 xq_a_token

channels/xueqiu.py 的匿名兜底访问 https://xueqiu.com 来取会话 cookie,但雪球现在首页只下发 acw_tc,不再下发 xq_a_token,于是后续 quote 调用必然 400016。

https://xueqiu.com/hq(以及 /about)仍会下发完整的匿名 token 组。

复现(Mac UA 与 Windows UA 结果一致):

import http.cookiejar, urllib.request
UA = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 "
      "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")

for page in ["https://xueqiu.com/", "https://xueqiu.com/hq"]:
    jar = http.cookiejar.CookieJar()
    op = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
    op.open(urllib.request.Request(page, headers={"User-Agent": UA}), timeout=15)
    print(page, [c.name for c in jar])

输出:

https://xueqiu.com/   ['acw_tc']
https://xueqiu.com/hq ['acw_tc', 'xq_a_token', 'xqat', 'xq_r_token', 'xq_id_token', 'cookiesu', 'u']

用首页的 cookie 调 quote:

HTTP Error 400
{"error_description":"遇到错误,请刷新页面或者重新登录帐号后再试",
 "error_uri":"/v5/stock/quote.json","error_data":null,"error_code":"400016"}

修复:把常量换成会下发 token 的页面即可,一行:

-_XUEQIU_HOME = "https://xueqiu.com"
+_XUEQIU_HOME = "https://xueqiu.com/hq"   # 首页已不再下发 xq_a_token

改完后 get_stock_quote / search_stock / get_hot_stocks / get_hot_posts 四个方法在完全匿名(config 里没有任何 xueqiu cookie)的情况下全部返回真实数据,doctor 变成 status: ok。建议顺带把 backends = ["Xueqiu API (需要登录 Cookie)"] 的文案改掉——这几个接口并不需要登录态。


Bug 2:config.yaml 里过期的 xueqiu_cookie 会静默屏蔽匿名兜底,且没有清除入口

_ensure_cookies() 的优先级是「配置文件 cookie → 首页兜底」,一旦 ~/.agent-reach/config.yaml 里存过一个 xueqiu_cookie即使它已经过期_load_cookies_from_config() 也会返回 True,兜底永远不执行。

我这台机器上就是这个状态:之前某次 configure --from-browser 存下的 xq_a_token 早已失效,于是即便修好了 Bug 1,doctor 仍然 400016,直到手工把这行从 config.yaml 里删掉才恢复。

agent-reach configure 的 positional choices 是 {proxy, github-token, groq-key, openai-key, twitter-cookies, youtube-cookies, xhs-cookies}没有 xueqiu 项,用户没有受支持的办法清除或改写这个 key,只能手改 YAML。

check() 的报错文案也只建议「重新 configure --from-browser」,完全没提到「你存的 cookie 可能已经过期并正在屏蔽兜底」,把人往错误方向引(这大概也是 #219 当时被误判成"必须登录"的原因之一)。

建议

  1. 配置里的 cookie 失败时降级到匿名兜底,而不是直接抛错——_load_cookies_from_config 成功注入 ≠ cookie 有效。
  2. check() 识别 400016,明确提示「已保存的 xueqiu_cookie 可能已过期,可删除 ~/.agent-reach/config.yaml 中的 xueqiu_cookie 后重试」。
  3. configure 增加 xueqiu-cookie positional(或一个通用的 --unset <key>),让用户能清除失效凭据。

验证

打完 Bug 1 的补丁 + 清掉过期 cookie 后(匿名,无登录态):

doctor:      xueqiu status=ok, active_backend="Xueqiu API"
quote:       中国平安 57.23 +2.53%
search:      SH600036 招商银行 / 03968 招商银行 / CIHKY 招商银行ADR
hot_stocks:  中际旭创 / 招商银行 / 古井贡酒
hot_posts:   正常返回作者与正文