因为requests只发送http请求并接收原始html,不执行javascript,而动态内容由js在浏览器中通过fetch/axios等异步加载并渲染,初始html中仅含空容器,真实数据藏于后续api响应或js执行结果中。

为什么 requests 直接请求拿不到动态加载的内容?
因为 requests 只发 HTTP 请求、收 HTML 文本,它不执行 JavaScript。如果页面内容靠 fetch()、axios 或 Vue/React 初始化后渲染,原始 HTML 里往往只有空容器或占位符(比如 <div id="app"></div>),真实数据藏在后续的 JS 执行或 API 响应里。
常见错误现象:用 requests.get(url).text 打印出来全是空标签,或者看到 data-v-xxx 这类 Vue 属性但没内容;用浏览器开发者工具看 Network → XHR,却能看到一堆带 JSON 的接口请求——说明数据根本不在初始 HTML 里。
解决思路不是“绕过”,而是「定位真实数据源」或「模拟浏览器行为」:
- 优先查 Network 面板,过滤 XHR/Fetch,找带
.json、/api/、?page=的请求,直接用requests调这些接口(最轻量) - 若接口有签名、时间戳、加密参数,需逆向 JS(比如搜
sign、token、crypto关键字) - 实在无法复现逻辑,再考虑启动浏览器自动化,但别一上来就用 Selenium
什么时候该用 Playwright 而不是 Selenium?
Playwright 和 Selenium 都能执行 JS,但 Playwright 启动更快、API 更一致、默认支持等待网络空闲(page.wait_for_load_state("networkidle")),对现代 SPA 更友好。
典型使用场景:
- 需要等某个元素出现后再提取(
page.wait_for_selector("#list-item")) - 页面有下拉加载、点击翻页等交互(
page.click("button.next")) - 要截取渲染后的 PDF 或截图(
page.pdf())
注意坑点:
-
Selenium的WebDriverWait容易写成轮询式等待,而Playwright的wait_for_*是事件驱动,更可靠 -
Playwright默认无头,但某些网站会检测headless字符串,可加chromium.launch(headless=False)或用user_agent伪装 - 别用
time.sleep()等页面加载,它不可靠;用page.wait_for_timeout(2000)仅作兜底
如何从混淆的 JS 中快速定位数据请求逻辑?
打开浏览器开发者工具 → Sources → Ctrl+P 搜 .js 文件,然后搜索关键词:fetch、axios、XMLHttpRequest、/api/、POST、GET。重点看调用栈顶部的函数名(比如 getData()、loadList())。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
如果 JS 被压缩(全是 a(), b()),按 Ctrl+Shift+P → 输入 “Pretty print”,格式化后再搜。
关键参数常出现在:
- URL 拼接处(
url: "/api/list?page=" + page) - 请求头(
headers: { Authorization: "Bearer " + token }) - 请求体(
body: JSON.stringify({ ids: [1,2,3] }))
用 console.log() 在疑似函数开头打日志(右键 → “Add log point”),刷新页面看控制台输出,比断点更快定位实际入参。
用 requests 模拟带 Token 的 API 请求要注意什么?
很多动态站把 Token 放在请求头(Authorization)、Cookie 或 URL 参数里。Token 往往有时效性(如 30 分钟),且可能和设备指纹、时间戳、用户登录态强绑定。
实操建议:
- 先在浏览器 Network 里复制完整请求(右键 → Copy → Copy as cURL),再用在线工具转成 Python
requests代码(比如 curlconverter.com) - 检查 Cookie 是否含
sessionid或_token,用requests.Session()复用会话,避免每次重新登录 - 若 Token 由 JS 计算生成(比如
HmacSHA256(timestamp + secret)),必须用 Python 复现相同逻辑,注意编码(utf-8)、时间格式(int(time.time()))、密钥是否 base64 解码 - 别硬编码 Cookie 或 Token 字符串——它们会过期;要么每次从登录响应中提取,要么封装成自动刷新逻辑
真正麻烦的从来不是“怎么渲染”,而是“怎么让服务端相信你是合法客户端”。JS 渲染只是表象,背后是反爬策略的博弈。参数生成逻辑、时效控制、行为特征,这些才是调试时最耗时间的地方。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










