from __future__ import annotations import random from typing import Any, Literal ProfileName = Literal["mobile", "desktop"] _MOBILE_UAS: tuple[str, ...] = ( ( "Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 " "(KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1" ), ( "Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/122.0.0.0 Mobile Safari/537.36" ), ) _DESKTOP_UAS: tuple[str, ...] = ( ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" ), ( "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" ), ) _XHS_ORIGIN = "https://www.xiaohongshu.com" _XHS_REFERER = "https://www.xiaohongshu.com/" def pick_random_profile() -> ProfileName: return random.choice(("mobile", "desktop")) def pick_user_agent(profile: ProfileName) -> str: pool = _MOBILE_UAS if profile == "mobile" else _DESKTOP_UAS return random.choice(pool) def resolve_profile_for_request(_config: Any | None = None) -> ProfileName: return pick_random_profile() def build_browser_headers( *, profile: ProfileName = "mobile", user_agent: str | None = None, cookie_header: str | None = None, with_cookie: bool = True, accept: str | None = None, extra: dict[str, str] | None = None, ) -> dict[str, str]: """构造接近真实浏览器的请求头(用于 CDN 图片等)。""" ua = user_agent or pick_user_agent(profile) if profile == "desktop": headers: dict[str, str] = { "User-Agent": ua, "Accept": accept or "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", "Accept-Encoding": "gzip, deflate, br", "Referer": _XHS_REFERER, "Origin": _XHS_ORIGIN, "Connection": "keep-alive", "sec-ch-ua-mobile": "?0", "Sec-Fetch-Dest": "document", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-Site": "same-origin", } else: platform = '"Android"' if "Android" in ua else '"iOS"' headers = { "User-Agent": ua, "Accept": accept or "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9", "Accept-Encoding": "gzip, deflate, br", "Referer": _XHS_REFERER, "Origin": _XHS_ORIGIN, "Connection": "keep-alive", "sec-ch-ua-mobile": "?1", "sec-ch-ua-platform": platform, "Sec-Fetch-Dest": "document", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-Site": "same-origin", } cookie = cookie_header if cookie is None and with_cookie: from xhs_bridge.config import load_config from xhs_bridge.extension_cookies import get_cookie_header_from_extension try: cfg = load_config() cookie = get_cookie_header_from_extension(cfg.skills.bridge_ws_url) except Exception: cookie = "" if cookie: headers["Cookie"] = cookie if extra: headers.update(extra) return headers