Skip to content

常见的反扒虫策略

约 2998 字大约 10 分钟

2025-06-13

随着网络爬虫技术的普及,网站为了保护数据安全和服务器资源,采用了各种反爬虫技术。

爬虫一般具备以下特征:

  • 高频访问
  • 抓取 html 内容
  • 抓取 数据接口
  • 模拟用户行为,如借助 SeleniumPyppeteer 等工具

由于 Selenium、Pyppeteer 等工具的存在,像 User-Agent + Referer 检测 很容易就被绕过。

而 IP 限制频次,很容易就能通过代理 IP 池 进行绕过,当然,我们也可以建立黑名单 IP 池来封禁这些被识别为爬虫的 IP。

而且现在的图像识别技术越来越成熟,包括 AI 识图也越来越准确,一些简单的图片噪点验证码早已完全失去了其作用,成为只会影响用户体验的方案。当然现在也有很多如滑动验证码、人脸识别等方案能够 提供更好的反爬虫保护。

一些具体的手段:

无限循环 + debugger

第一种常见的是,在源代码中 加入 debugger 语句,当打开控制台时,就会进入调试模式。

由于程序一直卡在 debugger 上,无法进行断点调试,网页的请求也看不到。

function bun() {
  setInterval(() => {
    debugger;
  }, 50);
}
try {
  bun();
} catch (err) {}

反制措施

无限 debugger 通常只能 防止 新手小白 ,但对于有一定经验的 技术人员来说,基本不会起到什么作用。

技术人员可以通过控制台中的 Deactivate breakpoints 按钮或者使用快捷键 Ctrl + F8 关闭无限 debugger; 还可以通过添加 add script ignore list 需要忽略执行代码行或文件。

于是,又衍生了一些更加复杂的变式:

通过 格式化代码 将 debugger 压缩在一行中,Deactivate breakpoints 按钮或者使用快捷键 Ctrl + F8 就 无法关闭 debugger,但 add script ignore list 依然能够阻止 debugger 运行。

function bun() {
  setInterval(() => {
    debugger;
  }, 50);
}
try {
  bun();
} catch (err) {}

进一步的,可以通过将 debugger 改写成 Function("debugger")(); 的形式来应对 add script ignore list

function bun() {
  setInterval(() => {
    new Function("debugger")();
  }, 50);
}
try {
  bun();
} catch (err) {}

检测窗口大小变化

当打开控制台时,如果是窗口内打开,控制台会吸附在侧栏,从而引起浏览器窗口变化。 可以通过检测外部窗口大小和内部窗口大小的差值,来侧面判断是否打开了控制台。

if (
  window.outerHeight - window.innerHeight > 200 ||
  window.outerWidth - window.innerWidth > 200
) {
  // 替换网页内容
  document.body.innerHTML = "检测到非法调试,请关闭后刷新重试!";
}

当检测到打开控制台后,我们可以直接替换网页的所有内容,或者重定向到一个新的空白窗口。 使之看不到正确的内容。

但其缺陷就是,如果控制台模式是选择窗口外打开的,并不会引起浏览器窗口变化。则无法判断是否打开了控制台。

但其实认真想一想,基于是否打开控制台 来判断是否有潜在爬虫行为,虽然有作用,但只有一点点 。

在 现代浏览器 Chrome ,从 117 版本开始, 提供了 Override content 的功能,它不仅可以在 Network 面板中发起 Mock 请求,还可以直接在 Sources 面板中,直接替换当前网页的资源内容。这意味着即使我们在代码中加入了这些检测,爬虫开发者完全可以直接在 Sourcs 面板中,直接修改网页内容,删除掉这些代码。

再者,还有比如 FiddlerCharles 等抓包工具,可以直接抓取到 内容,还包括 伪装 https 证书等。

基于是否打开控制台的检测形同虚设。可能带来的唯一收益就是防新手小白,其负面收益可能是 进一步提高了网站的所有者、维护者自己的调试、排查成本。

所以是否有这么做的必要,只能是见仁见智。

内容防御

当无论如何都不能防止爬虫触及内容,被爬取到网页内容或者数据,还可以继续在内容本身上进行防御。

在内容本身上进行防御,前提是保证正常的用户访问行为呈现到内容应该都是正确的, 再通过其他措施使爬虫行为读取到的内容是不正确的。

在这一方面,不同类型的网站会运用到不同的技术手段。

水印

对于 内容类的网站:

通常是给 图片添加 水印 ,水印包括 可见水印 和 隐藏式水印 。

字符混淆策略

常见的方法包括, 在文字内容中,插入不可见的字符,或者重新建立一套 Unicode 字符映射表,使源码中的字符与网页实际渲染的字符不一致。

但如果重新建立所有的字符映射表,其工作量将会变得很大,增加了很多不必要的复杂度,所以通常来说,只需要对部分关键的内容进行处理。

通过对关键内容的字符,采用一些技术手段进行处理,使得源代码中的字符与网页实际渲染的字符不一致, 确保用户看到的内容为真实内容,而爬虫获取的内容为包含混淆字符的内容。

font-face 字符集

font-face 在 CSS 中被用于定义字体。

iconfont 中的图标字体。 将关键内容的字符,使用 SVG 进行渲染,整合成一个字体文件,再通过 @font-face 定义字体,在网页源代码中,引入该字体库后,使用 unicode 编码编写内容,再渲染为正常的内容。

这种做法,由于关键内容被替换为了 unicode,爬虫只能爬取到 unicode 码,而不是真实的内容,它还需要解析 对应的字体库进行 编码映射,才能获取到真实内容,提高了爬取的复杂度。还可以通过 动态字体库,通过不定期的 更新 字体库的编码映射关系,来增加进一步爬取的复杂度。

background-image 拼凑

背景图片的拼凑,一般是运用在一些关键内容为数字、字母的场景上,因为其字符数量较少,转换为图片一般不会占用过多的资源,还可以使用“雪碧图”合并为一张图片,通过背景定位的方式控制显示的内容。

这种方式爬取到的内容只有一组空的标签,爬虫还需要进一步的读取 CSS 、获取图片、定位信息等才能分析获取内容。

字符穿插

字符穿插,主要是通过在正常的内容之间,插入不会被渲染的字符,但这些字符在源代码内容中,是可读取的。

比如, 12234 之间插入随机的其他数字:

<span>1</span><span>2</span><span>2</span><span>3</span><span>4</span>

插入随机数字

<span>1</span><span>3</span><span>2</span><span>2</span><span>3</span><span>6</span><span>4</span>

然后通过类名、选择器等方式,根据某些规则,将插入的随机数字进行设置为 display: node 等隐藏不显示。

这种方式 由于在正常的内容中插入了正常的内容,如果爬虫不知道规则的话,会误认为获取到了正确的内容,

伪元素隐藏

借助伪元素 ::before::after,将关键内容填充到 CSS 属性 content 中。

元素定位穿插

元素定位穿插,是将 正确的内容 进行 打乱重组,然后再通过 定位 的方式调整到 正确的顺序位置上。

shadowDOM 隐藏

shadowDOM 通过 Element.attachShadow() 方法给指定的元素挂载一个 Shadow DOM, 将关键内容写入到 Shadow DOM 中。 由于 Shadow DOM 的特性,可以指定其 modefalse, 拒绝从 js 外部访问关闭的 shadow root 节点。

即使爬虫 通过 Selenium、Pyppeteer 也读取不到内容。缺点就是 shadowDOM 的兼容性问题,可能会导致部分用户也看不到内容。

当爬虫行为在商业上带来的收益十分巨大时,就会投入更多的资源去应对反爬虫的措施,做出更有针对性的爬虫程序。

这一现象特别是在电商类、平台类的网站尤为严重。为了打出价格优势,需要及时的获取竞争平台的商品价格,调整自身平台的价格、优惠策略等。包括了价格监控、价格变动监控、价格预警等等一些列措施。

往往当一方的反爬虫方案进行技术调整后,另一方的爬虫一旦获取不到内容,就会立即发出邮件、短信等进行预警通知。双方就形成了一种长时间的持久的互为攻防的拉锯战。

从现状来看,反爬虫是很难完全实现防御住爬虫爬取到内容的,而且爬虫也有各种手段判断是否爬取到了正确的内容。

既然杜绝不了,那么除了常规的必要的反爬虫措施之外,给爬虫一些真实内容,又有何不可呢,然后我们可以在真实内容中,掺杂上一些不那么真实的内容,又有何不可呢?

常见的反爬虫策略

1. 基于请求特征的检测

  • User-Agent 检测:检查请求头中的 User-Agent 是否合法
  • 请求频率限制:单位时间内过多请求会被封禁
  • 请求间隔检测:机器请求通常间隔固定,人类操作则随机
  • 请求头完整性检查:检查 Accept、Referer 等标准头是否存在

2. 基于行为的检测

  • 鼠标移动轨迹:检测是否有人类般的鼠标移动
  • 点击模式:检测点击位置和间隔时间
  • 页面停留时间:检测在每个页面的停留时间
  • 浏览路径:检测是否遵循常规浏览路径

3. 验证码机制

  • 传统验证码:扭曲文字、数字识别
  • 行为验证码:如滑动拼图、点选文字等
  • 智能验证码:如 Google reCAPTCHA
  • 短信/邮件验证码:需要人工输入接收的验证码

4. 动态页面技术

  • JavaScript 渲染:核心内容由 JS 动态生成
  • Ajax 异步加载:数据通过异步请求获取
  • Token 验证:每次请求需要携带动态生成的 token
  • 接口加密:API 返回数据经过加密处理

5. 数据混淆技术

  • 字体反爬:使用自定义字体映射
  • CSS 偏移:通过 CSS 定位打乱页面显示顺序
  • 图片化数据:将关键数据转为图片格式
  • 数据分块加载:分多次请求完整数据

6. 账号与登录限制

  • 强制登录:必须登录才能查看内容
  • 访问权限分级:不同级别账号看到的内容不同
  • 账号行为监控:异常账号会被限制或封禁

7. 其他高级技术

  • WebAssembly 检测:通过 WASM 进行环境检测
  • Canvas 指纹:利用 Canvas 生成浏览器指纹
  • WebGL 指纹:通过 WebGL 渲染生成设备指纹
  • 流量分析:分析网络流量模式识别爬虫

应对反爬虫的建议

  1. 遵守 robots.txt 协议和网站使用条款
  2. 合理设置请求间隔和频率
  3. 使用高质量的代理 IP 池
  4. 模拟人类操作行为
  5. 优先考虑官方 API(如果可用)
  6. 必要时与网站方沟通获取合法数据访问权限

使用爬虫技术时应始终遵守相关法律法规,尊重网站的数据权益和服务器资源。

更新日志

2025/8/24 08:17
查看所有更新日志
  • e7112-1