"""浏览器导航请求头构造 抓取链路与登录态链路都要把 httpx 请求伪装成一次正常的浏览器页面导航,头部结构 完全一致,只有 User-Agent 以及随之联动的 `sec-ch-ua-mobile` / `sec-ch-ua-platform` 不同。结构留在这里共用,UA 常量则各自持有: - 抓取侧的 UA(`scraping/core/site.py`、`scraping/core/rakuma_site.py`)为反爬表现服务, 换了只影响抓取成功率。 - 登录态侧的 UA(`trading/core/auth_site.py`)必须与人工登录时浏览器用的那一个一致, 换了可能触发站点的设备校验,使已落盘的 cookie 直接失效。 值今天相同,变更理由不同,因此不合并成一份常量。 """ from __future__ import annotations from typing import Final ACCEPT_LANGUAGE: Final = "ja,en-US;q=0.9,en;q=0.8" def navigation_headers(user_agent: str, *, mobile: bool) -> dict[str, str]: """构造一套完整的浏览器导航请求头 乐天前置 Akamai Bot Manager,请求头不完整时不会直接封禁,而是把响应拖到 ~11s(实测与响应体大小无关,22 字节的响应同样耗时 11s);补齐下列头并复用 Akamai 下发的 cookie 后,稳定在 ~0.6-0.9s。ラクマ 无此限速,但沿用同一套头 没有代价,两侧保持一致更省心。 """ return { "User-Agent": user_agent, "Accept": ( "text/html,application/xhtml+xml,application/xml;q=0.9," "image/avif,image/webp,image/apng,*/*;q=0.8," "application/signed-exchange;v=b3;q=0.7" ), "Accept-Language": ACCEPT_LANGUAGE, "sec-ch-ua": '"Chromium";v="131", "Not_A Brand";v="24", "Google Chrome";v="131"', "sec-ch-ua-mobile": "?1" if mobile else "?0", "sec-ch-ua-platform": '"iOS"' if mobile else '"Windows"', "Sec-Fetch-Dest": "document", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-Site": "none", "Sec-Fetch-User": "?1", "Upgrade-Insecure-Requests": "1", }