这段时间一直在处理一个数据采集任务,最初用的是老一套 requests + 解析,结果对方某个页面突然升级成了动态渲染方案——打开浏览器时数据正常,查看源码干干净净,甚至连 XHR 接口都加了动态 cookie 校验。遇到这种情况基本逃不掉两条路:要么在 Python 爬虫里接 Selenium,要么上 Playwright。但问题也来了,这俩自动化工具只要参数没调对,运行几分钟就会被识别并封禁,而这个"识别 -> 封禁"的过程往往发生在你看不到的地方。
这篇文章不打算讲安装教程,重点聊聊我在动态渲染页面反爬对抗里实际用过的方案、Selenium/Playwright 的防检测参数怎么配置,以及为什么很多看似正常的代码会被风控系统一眼看穿。适合已经写过一些爬虫、正被动态页面和风控劝退的 Python 开发者,也适合刚接触浏览器自动化但不想只停留在 demo 阶段的朋友。
1. 拿到页面源码不等于拿到数据:先认清动态渲染的真实机制
1.1 requests 读回来的 HTML,常常只是一副空壳
大部分人对动态渲染的理解停留在"页面上有 JS",这个认知太模糊了。真正动态渲染的页面,requests 获取到的 HTML 往往是一个空壳:里面只有 <div id="app"> 之类的挂载点,真正的表格、列表、图表内容都是浏览器执行 JavaScript 之后,由框架动态插入到 DOM 里的。
举个例子,我最初用 requests 抓一个数据平台时,返回的 HTML 里能看到 20 多个 JS 文件路径和一个空的 root 节点。这种结构意味着数据不在初始 HTML 里,而是由前端 JS 通过异步请求拿到 JSON,再渲染成页面。这种情况下如果只靠 requests 拿 HTML 再解析,无论正则还是 XPath 都无从下手。
但是,这里有个容易被忽略的判断:不要看到 JS 渲染就慌着上 Selenium。先用浏览器的开发者工具切到 Network 面板刷新页面,观察到底触发了哪些请求。很多时候数据其实在接口里已经返回了,只是前端用 JS 把它们渲染到页面上。如果 XHR 或 Fetch 请求能找到完整的 JSON 数据,那最优解仍然是 requests/python-httpx 直接调接口,顺便带上接口需要的 headers 和 cookies,完全没必要启动一个浏览器。
1.2 哪几类场景,才是非浏览器自动化不可
真正逼着你上 Selenium/Playwright 的,通常是几类特殊的"反爬存根机制",我在项目里整理过三类高频场景。
第一类是动态 Cookie 校验。页面加载时会先在本地执行一段自定义 JS(比如某些金融资讯站用混淆后的 chameleon 脚本),计算出一个带有签名特征的 Cookie,后续的数据接口请求只有带上这个动态 Cookie 才能返回正常数据。这类逻辑如果靠手写 Python 去还原 JS 加密过程,成本极高,因为对方可能每周都换算法。用浏览器自动化的思路就简单了——让真实浏览器去执行 JS,再把生成好的 Cookie 拿回来用。
第二类是动态 iframe 嵌套。页面主体看似简单,但数据被塞进多个同源或跨域的子框架里。普通 requests 拿到的 HTML 只能看到 iframe 标签,iframe 的 src 往往又是前端生成或延后加载的。此时用 scrapy 配合 playwright 处理动态 iframe,比纯 requests 拼接几个请求要省心得多。
第三类是事件触发加载。比如点击"查询"按钮、拖动滑块、滚动到页面底部才加载更多内容,又比如鼠标悬浮才显示的价格。这些交互行为背后依赖一整套前端状态管理,纯 HTTP 层模拟会把代码写得非常脆。浏览器自动化是自然解。
1.3 选型之前,先回答三个问题
面对一个动态渲染页面,我会在写代码前先回答三个问题,省下大量踩坑时间:
- 目标数据是只在浏览器渲染后出现在 DOM 中,还是 Network 面板中的某个请求已经返回了完整数据?如果是后者,优先直接调接口。
- 目标接口的请求头或 Cookie 是否包含动态生成值?可以尝试在无痕窗口手动复制一段 Cookie 放到 requests 里测试,若十几分钟后就失效,大概率有动态校验。
- 目标网站本身是否已经布了强风控?判断标准包括:普通浏览器访问偶尔弹出验证码、无头浏览器访问直接被重定向到验证页、访问频率稍微提高就返回 202/302 之类异常状态码。如果是,后面的防检测章节必须仔细看。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 为什么 Selenium 一开就被封:站点到底在检测什么
2.1 自动化工具的三层暴露面
浏览器自动化之所以会被识别,是因为无论 Selenium 还是 Playwright,本质上都是"人类用真浏览器 + 驱动的外部控制"。只要没有做额外处理,这种控制活动会通过三个层面暴露给网页:协议层、特征层、行为层。
协议层指浏览器开发者工具协议(Chrome DevTools Protocol)与 WebDriver 协议。网页里的 JS 可以通过 navigator.webdriver 属性来判断当前浏览器是否由自动化驱动控制,有些站点还会通过 window.cdc_ 开头变量检测 WebDriver 注入痕迹,这类代码在浏览器环境执行,普通用户访问的值和自动化访问的值存在差异。
特征层指浏览器环境中各种容易被比对的对象,比如 navigator.plugins、navigator.languages、window.chrome、WebGL 渲染器信息、Canvas 指纹、字体列表、屏幕尺寸等。这些值在正常 Chrome 与自动化默认配置下会有明显区别,风控系统把一次访问的几百个特征映射成向量,与真实用户聚类结果对比后就能给访问者打上风险分。
行为层指鼠标移动轨迹、点击间隔、滚动速度、表单填写节奏。自动化测试常见的"瞬间点击""匀速移动"本身就是最好识别的标志。像 Selenium 官方示例那样 driver.find_element().click() 之后立即抓数据,真实用户不可能零延迟完成,即便特征全伪装好了,行为分也会暴露你。
2.2 站点检测自动化浏览器的几个常见特征点
下面这张表是我在调试时最常检查的特征。注意,不需要保证每个特征都和真人一模一样,关键是别出现明显可定向识别的少数几个点。
| 特征 | 检测位置 | 识别原理 | 常见伪装方法 |
|---|---|---|---|
| navigator.webdriver |
