Sitelet https://github.com/NanmiCoder/MediaCrawler/pull/986
Skip to content

fix(xhs): httpx 请求使用浏览器真实的 User-Agent 和 Client Hints - #986

Open
ChrisDoufu wants to merge 1 commit into
NanmiCoder:mainfrom
ChrisDoufu:pr/xhs-real-user-agent
Open

ChrisDoufu wants to merge 1 commit into
NanmiCoder:mainfrom
ChrisDoufu:pr/xhs-real-user-agent

Conversation

@ChrisDoufu

Copy link
Copy Markdown

问题

小红书的 API 客户端和媒体下载器用的是写死的请求头,和浏览器本身不一致:

  • create_xhs_client 发送 user-agent: ... Macintosh ... Chrome/137,同时发送 sec-ch-ua: ... v="136" 和 sec-ch-ua-platform: "Windows"。这两组值本身就互相矛盾。
  • _media_headers 使用 self.user_agent,即 Macintosh ... Chrome/126。

默认的 CDP 模式(ENABLE_CDP_MODE = True,CDP_CONNECT_EXISTING = True)会复用用户自己的 Chrome。CDPBrowserManager._create_browser_context 直接使用已有的 context,所以页面不会用 self.user_agent,发出的是 Chrome 的真实 UA。结果是同一个会话、同一组 Cookie,以三种不同的浏览器身份访问小红书:页面、API 请求、媒体下载各不相同。这是风控很容易识别的特征。

改动

新增 XiaoHongShuCrawler.read_browser_identity()。页面加载后,从页面读取 navigator.userAgent 和 navigator.userAgentData,然后:

  • 用真实 UA 替换 self.user_agent,API 客户端和媒体下载器都使用它;
  • 按浏览器的 brands、mobile、platform 生成 sec-ch-ua、sec-ch-ua-mobile、sec-ch-ua-platform。如果浏览器没有 navigator.userAgentData,就不发送这三个头。

标准模式(非 CDP)不受影响:页面仍使用 launch_browser 设置的 UA,httpx 请求现在也和它保持一致。

测试

  • 用 Playwright 启动真实 Chrome,分别在默认 UA 和覆盖 UA 两种情况下调用 read_browser_identity(),确认 UA 和 Client Hints 与页面报告的值一致。
  • tests/test_xhs_core_access_error.py、tests/test_xhs_raw_response_errors.py 通过。

🤖 Generated with Claude Code

The API client and the media downloader used hardcoded headers: the API
client sent a macOS Chrome 137 user agent with Windows Chromium 136 client
hints, and media downloads sent a macOS Chrome 126 user agent. In CDP mode
the page is the user's own Chrome, so one session reached Xiaohongshu with
three different browser identities on the same cookies.

Read navigator.userAgent and navigator.userAgentData from the page after it
loads, and use them for both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant