{"record":{"id":"b475b1f19a0aa93f","repo":"jackwener/OpenCLI","slug":"xueqiu-com-b475b1","errorCode":null,"errorMessage":"xueqiu.com","messagePattern":"xueqiu\\.com","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/xueqiu/utils.js","lineNumber":50,"sourceCode":" * Fetch a xueqiu JSON API from inside the browser context (credentials included).\n * Page must already be navigated to xueqiu.com before calling this function.\n * Throws CliError on HTTP errors; otherwise returns the parsed JSON.\n */\nexport async function fetchXueqiuJson(page, url) {\n    const result = await page.evaluate(`(async () => {\n    const res = await fetch(${JSON.stringify(url)}, { credentials: 'include' });\n    if (!res.ok) return { __xqErr: res.status };\n    try {\n      return await res.json();\n    } catch {\n      return { __xqErr: 'parse' };\n    }\n  })()`);\n    const r = result;\n    if (r?.__xqErr !== undefined) {\n        const code = r.__xqErr;\n        if (code === 401 || code === 403) {\n            throw new AuthRequiredError('xueqiu.com', '未登录或登录已过期');\n        }\n        if (code === 'parse') {\n            throw new CommandExecutionError('响应不是有效 JSON', '可能触发了风控，请检查登录状态或稍后重试');\n        }\n        throw new CommandExecutionError(`HTTP ${code}`, '请检查网络连接或登录状态');\n    }\n    return result;\n}\n","sourceCodeStart":32,"sourceCodeEnd":59,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xueqiu/utils.js#L32-L59","documentation":"fetchXueqiuJson fetches xueqiu JSON APIs from inside the logged-in browser context and inspects the response status. When the API returns HTTP 401 or 403 it maps that to AuthRequiredError('xueqiu.com', '未登录或登录已过期'), signaling that the browser session lacks valid xueqiu credentials (cookies). xueqiu requires a logged-in session with a valid xq_a_token cookie for most v5 API endpoints; anonymous or expired sessions get rejected with 400/401/403.","triggerScenarios":"Calling any xueqiu CLI command (e.g. watchlist, groups) when the browser page was never logged into xueqiu.com, or the session cookie (xq_a_token) has expired, or xueqiu risk control rejects the request with 401/403.","commonSituations":"Cookie expired after days of use; fresh browser profile never logged in; scraping too fast triggers anti-bot 403; xueqiu changed token requirements; running headless without persisted login state.","solutions":["Open a xueqiu.com page in the CLI browser and log in manually to refresh the session cookies","Re-run the command after confirming the browser session is logged in","Slow down request frequency / wait if 403 was caused by rate limiting or risk control","Clear browser state and re-authenticate if cookies are corrupted"],"exampleFix":"// before (page never authenticated)\nawait page.goto('https://xueqiu.com');\nconst d = await fetchXueqiuJson(page, url); // throws AuthRequiredError\n// after (verify login before calling)\nawait page.goto('https://xueqiu.com');\nconst loggedIn = await page.evaluate(() => document.cookie.includes('xq_a_token'));\nif (!loggedIn) throw new AuthRequiredError('xueqiu.com', '请先登录 xueqiu.com');\nconst d = await fetchXueqiuJson(page, url);","handlingStrategy":"try-catch","validationCode":"const loggedIn = await page.evaluate(() => document.cookie.includes('xq_a_token'));\nif (!loggedIn) throw new Error('Not logged into xueqiu.com');","typeGuard":"function isAuthRequiredError(e) { return e instanceof AuthRequiredError; }","tryCatchPattern":"try {\n  const d = await fetchXueqiuJson(page, url);\n} catch (e) {\n  if (e instanceof AuthRequiredError) {\n    // prompt user to log into xueqiu.com in the browser session\n    return { error: 'AUTH_REQUIRED', hint: 'Login to xueqiu.com and retry' };\n  }\n  throw e;\n}","preventionTips":["Log into xueqiu.com once in the persistent browser profile before scripting","Persist browser session state so cookies survive restarts","Handle AuthRequiredError by prompting re-login rather than retrying blindly","Back off on repeated failures to avoid triggering risk control"],"tags":["auth","session-expired","xueqiu","http-401"],"backgroundTag":"auth-session-expired","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}