因为微博/小红书等平台Web端HTML精简,正文依赖JS动态调用API,而这些API校验User-Agent、Referer、X-Requested-With等头字段及Cookie或Authorization,PC端请求易被拦截返回空页或跳转登录。

为什么直接用 PC 端 User-Agent 抓不到微博/小红书的正文?
因为主流社交媒体(如微博、小红书、抖音)的 Web 端已大幅精简 HTML 结构,关键内容(如笔记正文、评论列表)全靠前端 JS 动态拉取 API,而这些 API 通常校验 User-Agent、Referer、X-Requested-With,甚至要求带有效 Cookie 或 Authorization 头。PC 浏览器请求过去,服务器直接返回空容器或跳转登录页。
真实移动端请求(比如 iPhone + Safari 或 App 内 WebView)则能拿到完整 JSON 数据——不是因为“移动端更受信任”,而是因为 App 或 M 版页面的请求路径、参数签名、Header 组合是服务端白名单认可的。
- 小红书 H5 页面的笔记详情接口形如
https://www.php.cn/link/652a805887302f460fa9d0f968fdee9dexplore/xxxxxx,但实际数据来自https://www.php.cn/link/652a805887302f460fa9d0f968fdee9dapi/sns/web/v2/note/page,且必须带X-Sign和X-B3-Traceid - 微博 M 站(
m.weibo.cn)的某条微博详情接口是https://m.weibo.cn/statuses/show?id=xxxx,但需Referer: https://m.weibo.cn/且Cookie中含有效SSOLoginState - 直接复用浏览器开发者工具里复制的「curl」命令,大概率失败——因为其中的
cookie过期快,sign类参数是时间敏感的一次性签名
如何稳定复现移动端请求头(不依赖抓包工具)?
别硬记 Header,用真实设备 UA + 最小必要字段组合。重点不是“像手机”,而是“和服务端预期一致”。
- 固定使用 iOS Safari 移动端 UA:
Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1 - 必加三项:
Accept: application/json(告诉服务端你要 JSON)、X-Requested-With: XMLHttpRequest(模拟 AJAX)、Referer: https://www.php.cn/link/652a805887302f460fa9d0f968fdee9d(域名必须和目标站主域一致,不能写错) - 禁用
Accept-Encoding: gzip, deflate——某些接口(如小红书)在开启 gzip 时会返回乱码或 403,关掉反而稳定 - 不要盲目加
X-Sign或X-TS:这些字段多为服务端校验签名,逆向成本高;优先找未签名的公开接口(例如小红书的搜索页/api/sns/web/v1/search/notes在未登录时仍可调用)
requests.get() 抓小红书搜索页 JSON 却返回 403?检查这三点
小红书对搜索接口的反爬极严,但并非无解。403 通常不是封 IP,而是请求“格式不对”。
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
-
headers中漏了X-App-Version:必须匹配当前 App 正式版号,例如7.92.0(查最新版号可看 App Store 页面或抓真机流量) -
params缺少source参数:值固定为web_search_result,缺了就 403 - URL 中的
keyword没做 URL 编码:中文关键词必须用urllib.parse.quote()处理,否则服务端解析失败返回 403 - 示例最小可行请求:
import requests
from urllib.parse import quote
<p>url = "<a href="https://www.php.cn/link/cce119502b39f2cd9f69219bb6dbd241">https://www.php.cn/link/cce119502b39f2cd9f69219bb6dbd241</a>"
params = {
"keyword": quote("咖啡教程"),
"page": 1,
"page_size": 20,
"source": "web_search_result"
}
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) ...",
"X-App-Version": "7.92.0",
"Accept": "application/json",
"X-Requested-With": "XMLHttpRequest",
"Referer": "<a href="https://www.php.cn/link/652a805887302f460fa9d0f968fdee9d">https://www.php.cn/link/652a805887302f460fa9d0f968fdee9d</a>"
}
resp = requests.get(url, params=params, headers=headers)</p><h1>resp.json() 可直接取 data.notes</h1>
微博 M 站接口需要登录态,但又不想搞 Selenium
微博的 m.weibo.cn 接口其实有“半公开”入口:未登录用户也能访问部分接口,只要 Cookie 里有有效的 ALF(过期时间戳)和 SUB(用户标识),而这两个字段可以从公开页面中提取。
- 先 GET
https://m.weibo.cn/api/config/serverTime,响应头里有Set-Cookie: ALF=xxx,这个ALF是服务端下发的、有效期数小时的时间令牌,无需登录即可获取 - 再 GET
https://m.weibo.cn/api/container/getIndex?type=all&queryVal=python&containerid=100103type%3D1%26q%3Dpython,带上刚拿到的ALF和一个伪造的SUB(如SUB=_2A25LzrZvDeRhGeRK7lES-SzNzji3HXVr7RnYrDV6PUJbkdAKLVjnkW1NT55JtOZyQfGw0oIaC9xhT8sUd1QK7iP0),多数搜索接口就能返回数据 - 注意:
containerid不是固定值,需从搜索页 HTML 的window.$render_data中正则提取,或用https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3Dxxx先试探 - 绕过登录的关键是:不要执着于“模拟完整登录流程”,而要识别哪些字段是服务端真正校验的、哪些只是“摆设”
移动端请求不是银弹,但把 UA、Referer、关键自定义 Header、参数编码这几项做扎实,比堆代理池或上 Puppeteer 更快见效。最难的从来不是“怎么发请求”,而是“哪条请求真的被服务端当人看”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










