现代网站反爬虫方案已经从过去单一特征匹配,改成多特征关联判断。
具体来说,现代网站会通过指纹(Browser Fingerprinting)、请求属性(IP)、行为、环境一致性等特征去判断是不是爬虫。因此,理想中的爬虫应该尽可能地去模拟真实用户。
1. 技术选型
以前方案存在的一个巨大缺陷:
禁用 JavaScript 会被直接标记为异常配置——现代浏览器没有禁用 JS 的正常用户。
另外,仅靠 Cookie 匿名无法应对 Fingerprint 追踪;机械化的自动化操作(固定间隔点击、表单粘贴而非逐字输入)在行为模型面前无处遁形。
新方案的核心逻辑:多维关联 + 行为仿真 + 特征封堵。三者必须同时满足,否则关联校验会将矛盾点放大为高置信度的 Bot 判定。
2. 核心代码(伪代码)
以下是关键检测点与对抗逻辑的伪代码实现:
请求属性关联校验(最易被忽视):
# 反爬系统视角:属性一致性检查
def validate_request_consistency(request):
ip_geo = geo_lookup(request.ip) # 美国
lang = request.headers.get('Accept-Language') # zh-CN
timezone = request.timezone # Asia/Shanghai
# 三者不匹配 → Bot 置信度 +60%
if not (ip_geo.country in lang and ip_geo.timezone == timezone):
return flag_as_suspicious(reason="miscorrelation")
- 要点:IP 属于美国机房,
Accept-Language却是zh-CN,时区是Asia/Shanghai——三项属性互相矛盾,这是最常见的低级错误。 - 对策:三者必须从同一地理区域生成,不能各自独立配置。
WebRTC 真实 IP 泄露:
// 浏览器通过 WebRTC 的 STUN 请求暴露内网/公网 IP
// 即使使用代理,WebRTC 仍会绕过代理直连
const pc = new RTCPeerConnection({ iceServers: [] });
pc.createDataChannel('');
pc.createOffer().then(offer => pc.setLocalDescription(offer));
pc.onicecandidate = (e) => {
if (e.candidate) {
// 这里会暴露你的真实 IP,即使走了代理
console.log("Leaked IP:", parseCandidate(e.candidate));
}
};
- 要点:代理只能拦截 HTTP 层流量,WebRTC 走的是 UDP 的 STUN 协议,完全绕过代理。
- 对策:Playwright/Puppeteer 中需通过
--disable-webrtc或注入脚本禁用 WebRTC。
注意:完全禁用 WebRTC 也是一种指纹特征(正常用户很少禁用)。更高级的方案是“Mock WebRTC”,即允许它运行但返回代理服务器的 IP。
行为时序仿真:
# 错误:瞬间填充表单
await page.fill('#search', 'keyword') # 0ms 完成,非人类
# 正确:逐字符输入 + 随机延迟
async def human_type(page, selector, text):
for char in text:
await page.type(selector, char, delay=random.randint(50, 150))
if random.random() < 0.05: # 5% 概率打错再删除
await page.keyboard.press('Backspace')
await asyncio.sleep(random.uniform(0.1, 0.3))
await page.type(selector, char, delay=random.randint(80, 120))
- 要点:
page.fill()底层是直接设置 DOM value,不触发keydown/keyup/keypress事件链,反爬系统检测事件时间戳分布即可识别。 - 对策:逐字符输入,引入随机延迟和偶尔的打字纠错行为。
3. 注意事项
- 浏览器性能基准检测:反爬系统会采集 Canvas 渲染速度、JS 引擎执行时间等性能指标,与同配置设备的基准对比。虚拟机或 Docker 环境的性能特征与物理机差异显著,容易被识别。
- Cookie 策略的两难:完全没有 Cookie 的请求比有 Cookie 的更可疑(正常用户总有历史访问记录);但 Cookie 本身又是追踪载体。平衡点在于维护一份真实的 Cookie 演进链。
- 识别网站的惩罚信号:封禁不总是返回 403。常见策略包括:返回 404(让你以为页面不存在)、弹出 Captcha(消耗你的验证资源)、返回 Fake data(最危险——你不知道数据是假的)。如果采集到的数据突然变得异常整齐或缺失关键字段,大概率命中了蜜罐策略。
- Cipher Suite 指纹:TLS 握手阶段,客户端发送的 Cipher Suite 列表是设备指纹的一部分。Python
requests库的 Cipher Suite 与 Chrome 完全不同,一眼可辨。需使用curl_cffi或tls-client等支持 TLS 指纹伪装的库。需要特别注意JA3 指纹,这是目前大厂(如 Cloudflare、Akamai)识别爬虫的核心手段。
4. 进阶
IP 代理池与调度策略
问题:单 IP 高频请求必然触发速率限制
对策:
- 使用代理 IP 池。推荐使用蜻蜓代理,我们提供企业级的代理IP服务, IP 纯净度高和分布式节点,满足企业级需求。
- 按 IP 地理位置与目标站点区域匹配调度,避免跨区域跳转。
- 维护 IP 健康度评分,被封 IP 及时剔除,单个 IP 请求间隔不低于 30 秒。
- 对于高安全等级站点,采用轮换 + 粘性会话混合策略:同一 session 内保持 IP 不变,session 结束后切换。
分布式调度与指纹隔离
问题:单机多实例共享同一设备指纹,关联分析可轻易聚类识别。蜻蜓代理建议:在配合我们的高匿名代理时,务必结合独立的浏览器 Profile。只有 IP 层的隔离是不够的,必须实现‘一 IP、一环境、一指纹’的深度解耦。”
对策:
- 每个爬虫实例维护独立的浏览器 Profile(Cookie、LocalStorage、Cache 独立)。
- 实例间 IP、User-Agent、屏幕分辨率等指纹参数互不重叠。
- 使用任务队列(如项目中的 p-queue)控制并发粒度,避免瞬间流量突增。
- 调度层引入随机抖动(Jitter),在固定间隔基础上叠加随机偏移,打破周期性模式。

