1. 引言
随着搜索引擎技术的诞生甚至更早的时间,网络爬虫就开始在互联网泛滥,网络爬虫给相关的网站服务器造成了沉重的负担。近年来随着大模型技术的发展,相关数据的需求激增,网络爬虫的数量也随着快速增长。在《2025年Imperva恶意爬虫报告》[1]中明确指出恶意爬虫产生的流量占全球网络流量的37%,较2023年的32%有了显著增长。这些爬虫造成服务器数据的流失,个人信息的泛滥,服务器的成本增加,甚至导致服务器瘫痪,因此,反爬虫技术需要提升,以应对相关爬虫流量的泛滥,数据外泄的风险,服务器的高负载。
2. 整体技术架构
Figure 1. System architecture
图1. 系统架构
整体架构(如图1)分为如下7个大的组成部分:
1、基于Web前端的反爬机制
2、基于图像识别与逻辑运算的验证码机制
3、基于蜜罐的反爬虫机制
4、基于令牌机制的请求参数自动生成机制
5、深度学习模型
6、规则库机制
7、黑白名单机制
系统从多个机制来对页面进行反爬,每个机制都有一定的拦截能力,通过整体的防御方法可以实现整体的防御。下面我们从具体的每一个机制展开说明。
3. 基于Web前端的反爬机制
Web1.0架构的网站大多页面和数据样式都集中在页面的html中,这样的好处是数据以及展示在一起,数据加载很快。但也有一个缺点,就是网页爬虫只需爬取这个页面就获取数据,单独制定特殊的数据保护策略很难。Web2.0的网页架构大多是页面样式和数据分离的,浏览器加载样式文件后,会调用数据接口获取数据。这对于屏蔽网络爬虫还是比较有帮助的,网络爬虫如想获取相关数据,都需要对每一个网站的数据接口进行单独构建数据获取流程,增加网络爬虫的工作量[2]。从而可以屏蔽大量的通用爬虫。另外对正常用户来说,其终端浏览器会加载样式,图片等文件,有些只采集数据的程序反而不会加载这些样式文件和图片文件,这些可以成为发现爬虫的特征。
动态加载机制,分为前端和后端两个策略,前端策略:检验参数是否合法,然后检验前端请求是否合法。合法下载前端的剩余代码,样式,以及其它前端资源。前端发起AJAX请求→返回数据→前端渲染。后端策略:获取相关请求,之后进行前端参数验证,确保请求为正常用户请求,之后进行数据查询和结果返回。
1) 前端方面(Vue 3 + Axios + crypto-js)
前端采用Vue 3作为核心框架,结合Axios进行异步数据请求,确保动态页面加载的高效性和灵活性。通过Vue Router实现按需加载,减少首屏渲染时间,提升用户体验。在数据安全方面,前端集成crypto-js库,使用AES对称加密对关键数据进行加密处理,确保敏感信息在传输过程中不被窃取。Axios拦截器会在请求发出前自动加密数据,并在接收响应后解密,整个过程对业务逻辑透明,不影响正常交互。此外,前端还会动态生成请求签名,防止恶意爬虫伪造请求,提高数据安全性。
2) 后端方面(RESTful API + AES加密)
后端采用标准的RESTful API架构,确保接口规范、易于维护和扩展。所有API均基于HTTPS协议传输,防止数据在传输过程中被劫持或篡改。后端同样使用AES对称加密对返回的数据进行加密,确保即使数据包被截获,也无法直接解析出有效信息。加密密钥采用动态生成机制,避免固定密钥带来的安全隐患。此外,后端会对每个请求进行合法性校验,包括请求头中的签名验证、时间戳防重放攻击等,有效防止爬虫自动化抓取数据。
3) 数据加密与传输安全
为确保数据在传输和存储过程中的安全性,系统采用AES-256加密算法对关键业务数据进行加密,前端和后端使用相同的加密逻辑,但密钥动态管理,避免长期固定密钥带来的风险。所有API通信均强制使用HTTPS,结合TLS 1.2+协议,防止中间人攻击(MITM)和数据泄露。加密后的数据即使被爬虫获取,也无法直接解析,大幅增加数据抓取难度。
4) 反爬虫与性能优化
除了加密措施外,系统还采用多种反爬虫策略,如:
•请求频率限制:防止短时间内大量请求导致服务器压力过大。
•动态Token验证:每次请求需携带动态生成的Token,防止自动化脚本爬取。
•虚假数据混淆:在真实数据中混入干扰信息,增加爬虫解析难度。
在性能优化方面,前端采用Vue 3的Composition API提升代码复用性,结合Axios的并发请求优化,减少网络延迟。后端通过缓存机制和负载均衡,确保高并发场景下的稳定响应。
4. 基于图像识别与逻辑运算的验证码机制
网站的用户通常是自然人,通过一些人类的行为校验能够阻断很多爬虫的访问,比较常用的方法有验证码,滑块,图案点击,逻辑运算等[3]。为有效阻断爬虫访问,本方案设计一种验证方案阻断网站爬虫的访问。
首先线下整理大量的数据问题和问题的答案,将相关问题和答案整理入库;当用户访问Web页面的时候,收集用户访问页面数据和时间点数据,IP数据,Cookie数据;访问IP或Cookie访问频率过高时,触发判别模型,判别模型使用深度学习模型,对用户当前信任度和最近的N步行为轨迹进行数据建模,输入深度学习模型,模型进而给出结论是不是触发验证码弹出。验证码弹出后,如果验证码错误则重新验证,如果累计错误太多,阻断访问,验证码正确,增加用户信任度。继续检测用户Web访问,直到用户结束访问,流程如图2所示。
Figure 2. Process of CAPTCHA
图2. 验证码流程
# 初始化阶段
1) 离线准备数据:
- 收集大量“问题和答案”对
- 构建问题答案数据库QA_DB
# 用户访问处理
2) 当用户访问网页时:
- 记录访问数据:
user_ip = 获取用户IP
user_cookie = 获取用户Cookie
current_page = 当前访问页面
access_time = 当前时间戳
- 更新访问日志:
append(access_log, [user_ip, user_cookie, current_page, access_time])
# 频率检测
3) 实时监控访问频率:
- 计算IP访问频率:ip_freq = 统计(user_ip, 时间窗口T内的访问次数)
- 计算Cookie访问频率:cookie_freq = 统计(user_cookie, 时间窗口T内的访问次数)
if ip_freq>频率阈值 or cookie_freq>频率阈值:
# 触发判别模型
调用深度判别模型(user_ip, user_cookie)
# 深度学习判别模型
4) 深度判别模型(用户标识):
- 获取用户当前信任度trust_score = 查询信任度数据库(user_ip/user_cookie)
- 获取最近N步行为轨迹:
recent_actions = 获取最近N次访问记录(user_ip/user_cookie)
# 包括:访问页面序列、时间间隔序列、操作类型等
- 构建模型输入特征:
features = [trust_score] + 提取行为特征(recent_actions)
- 使用预训练深度学习模型预测:
trigger_captcha = 模型预测(features)
iftrigger_captcha == True:
# 需要弹出验证码
显示验证码界面(user_ip/user_cookie)
# 验证码处理流程
5) 显示验证码界面():
- 从QA_DB随机选择问题Q
- 向用户展示问题Q
- 设置验证码超时计时器
6) 处理用户验证码响应():
- 获取用户答案user_answer
- 查询正确答案correct_answer = QA_DB[Q]
ifuser_answer == correct_answer:
# 验证码正确
更新用户信任度(user_ip/user_cookie, 增加信任值)
清除错误计数(user_ip/user_cookie)
允许继续访问()
else:
# 验证码错误
增加错误计数(user_ip/user_cookie)
error_count = 获取当前错误计数(user_ip/user_cookie)
if error_count>= 最大允许错误次数:
# 阻断访问
记录安全事件(user_ip/user_cookie, "多次验证失败")
显示阻断页面()
加入临时黑名单(user_ip/user_cookie)
else:
# 重新验证
显示验证码界面() # 显示新问题
# 持续监控
7) 用户继续访问时:
- 重复步骤2~6
- 直到用户会话结束
5. 基于蜜罐的反爬虫机制
蜜罐陷阱是一种主动防御技术[4],通过在网站/系统中设置虚假的、对正常用户不可见的诱饵元素,诱导恶意爬虫触发规则并实施拦截。前端代码动态给页面某些汉字加载蜜罐连接,如果页面被请求,相关链接会触发蜜罐机制,蜜罐链接触发后,对爬虫大量生成垃圾内容及蜜罐链接。
设计包含如下几个组成部分:
1) 原始数据掺入诱导数据模块:该模块负责从原始的生成带有诱导的原文数据,掺杂的数据很少而且比较隐蔽。
2) 纯垃圾页面生成模块:该模块负责纯垃圾页面,页面有大量的无效数据和链接。
3) 爬虫识别模块:该模块负责识别爬虫,识别后进行相关的这里来。
蜜罐陷阱网络反扒的安全策略设计如下:首先通过表单隐藏字段,CSS隐藏元素等方法设置蜜罐陷阱到需要访问的网页集中;同时生成大量的垃圾页面。当有IP进行Web访问触发到蜜罐陷阱时,根据访问频率等条件后,判定爬虫。如果某IP被判定为爬虫后,引导其进入垃圾页面,流程如图3所示。
# 初始化阶段
1) 在目标网页集中部署蜜罐陷阱:
- 在表单中插入隐藏字段(type="hidden")
- 创建CSS隐藏元素(display: none, visibility: hidden)
- 设置不可见链接(位置偏移屏幕外)
2) 生成垃圾页面库:
- 创建大量无意义页面(内容随机生成)
- 设计虚假数据接口
- 建立页面间随机跳转关系
# 访问监控阶段
3) 监听所有访问请求:
for 每个访问请求:
记录请求信息:1) 来源IP,2) 访问时间戳,3) 请求URL,4) 用户代理,5) 请求头信息
检查是否触发蜜罐:
if 请求包含隐藏字段值OR访问了CSS隐藏元素OR点击了不可见链接:
标记该IP为可疑爬虫
增加该IP的触发计数 +1
更新访问频率统计:
计算该IP单位时间内的请求次数
if 请求频率 > 阈值N:
标记该IP为高频爬虫
# 爬虫判定阶段
4) 判定爬虫行为:
if IP被标记为可疑爬虫 AND 触发计数 > M:
判定为爬虫
else if IP被标记为高频爬虫:
判定为爬虫
else:
允许正常访问
# 反制处理阶段
5) 对爬虫IP进行处理:
if IP被判定为爬虫:
生成垃圾页面跳转链接:
随机选择垃圾页面库中的页面
添加跳转参数(如:redirect_token=xxx)
响应重定向指令:
返回302重定向到垃圾页面
设置长期Cookie标记该爬虫
记录爬虫信息到日志:IP地址,触发时间,行为特征,处理措施
6) 垃圾页面处理:
while 爬虫继续访问:
每次请求返回不同垃圾页面
页面包含:1) 大量无效链接,2) 虚假数据接口,3) 随机跳转逻辑
目标:消耗爬虫资源,干扰数据采集
Figure 3. Process of Honeypots
图3. 蜜罐流程
6. 基于令牌机制的请求参数自动生成机制
在用户访问页面的时候,通过JS代码逻辑检测本地是否有最新的token,如果没有或者已经过期,弹出验证码,此时收集验证码请求信息,IP,浏览器Cookie和时间信息,通过加密算法构建token,加密过程发往服务器端,由服务器端返回最新的token。重新生成带有追加了token参数的URL请求地址,之后跳转到新的页面请求地址,再对新的请求验证最新的token是否合法,如果合法,生成正常页面,如不合法,返回固定页面,提出警告信息。
流程步骤设计如下:
我们根据描述来设计一个流程图。流程主要分为以下几个步骤:
Step:1. 用户访问页面。
Step:2. 检查本地是否有有效token (包括是否存在和是否过期)。
Step:3. 如果没有有效token,则弹出验证码要求用户输入。
Step:4. 验证用户输入的验证码。如果失败,则重新弹出(可以设置重试次数,连续验证直到成功)。
Step:5. 验证码成功后,收集信息(包括验证码信息、请求IP、浏览器cookie、请求时间等),通过加密算法构建一个请求体,发送到服务器端。
Step:6. 服务器端处理请求,根据自加密算法,计算出加密摘要,作为生成的token,返回最新的token。
Step:7. 客户端接收到token后,生成一个追加了token参数的URL,然后跳转到这个新的URL。
Step:8. 在新的页面请求中,服务器验证token的合法性。
Step:9. 如果合法,生成正常页面返回给用户。
Step:10. 如果不合法,返回一个固定警告页面。
7. 深度学习模型
在以上的机制中,都会遇到是否对访问的IP施加限制的问题:1) 前后端分离策略中,后端判断用户的访问是否频繁,2) 验证码的弹出依据,不能频繁地让用户输入验证码,3) 蜜罐机制中的验证码弹出逻辑,4) 验证码的弹出策略。这些都需要一个模型基于环境和访问信息确定是不是启动一些反爬或者人工隔离措施。
1、根据问题性质确定使用长短期记忆网络LSTM (Long Short-Term Memory)神经网络作为Web爬虫行为检测模型。长短期记忆网络是一种特殊的循环神经网络(RNN),专门设计用于解决传统,RNN在处理长序列数据时面临的梯度消失/爆炸问题,能够有效捕捉长距离依赖关系。其核心在于引入记忆细胞(Cell State)和门控机制(Gate Mechanism),通过控制信息的流动来实现对长期信息的存储与遗忘。
LSTM由记忆细胞和三个门控单元(遗忘门、输入门、输出门)组成,每个门控单元通过sigmoid激活函数输出0到1之间的数值,表示允许信息通过的程度(0表示完全禁止,1表示完全允许)。
1) 记忆细胞状态
记忆细胞状态就像一条信息传输的“高速公路”,它贯穿整个LSTM网络,负责在不同时间步之间传递信息。信息在记忆细胞状态中传递时,可以相对稳定地保留较长时间,避免了传统RNN中信息容易丢失的问题。遗忘门和输入门共同作用于记忆细胞状态,遗忘门决定删除哪些旧信息,输入门决定添加哪些新信息,从而实现对记忆细胞状态的更新。
2) 输入门
输入门负责处理当前时刻的输入信息,决定哪些新的信息会被添加到记忆细胞状态中。它利用sigmoid函数输出一个值,用于控制新信息的“准入程度”。同时,输入内容通过tanh函数生成一个候选值向量,这个向量包含了可能要添加到记忆细胞状态中的新信息。最后,将sigmoid函数的输出与tanh函数生成的候选值向量相乘,得到实际要添加到记忆细胞状态中的信息。
3) 遗忘门
遗忘门决定了上一时刻记忆细胞状态中哪些信息会被保留到当前时刻。它接收上一时刻的隐藏状态和当前时刻的输入,通过一个sigmoid激活函数输出一个0到1之间的数值。这个数值就像一把“钥匙”,数值越接近1,表示上一时刻的该部分信息被保留的程度越高;数值越接近0,则表示该部分信息被遗忘的程度越高。例如,在处理一段文字序列时,如果之前的内容与当前句子的主题关联不大,遗忘门就会降低这些信息的保留程度。
4) 输出门
输出门根据当前记忆细胞状态和隐藏状态,决定最终的输出。它首先使用sigmoid函数得到一个控制输出的向量。然后,对记忆细胞状态进行tanh处理,将处理后的记忆细胞状态与sigmoid函数的输出向量相乘,从而得到LSTM单元的最终输出。
一个典型的LSTM的单元结构(如图4)为:
Figure 4. LSTM unit structure
图4. LSTM的单元结构
这些说明LSTM特别适合解决时间访问序列类数据的检测问题。
2、数据收集与模型训练
为使用LSTM模型进行检测,首选需要收集数据,我们需要收集真实用户和爬虫的访问数据,之后我们进行相关特征的抽取,相关的特征包含访问端的信息和访问序列数据。收集的数据特征有:
特征字段 |
数据类型 |
数据解释 |
用户UA |
字符串 |
用户请求时候的useragent,通常的爬虫会标记自己的身份 |
用户的cookie |
字符串 |
用户标记用户的唯一属性 |
访问的页面位置 |
枚举型 |
首页,二级列表页,数据页 |
文件类型 |
枚举型 |
Html、css、图片、对象文件 |
访问时间 |
时间 |
时间戳 |
Session时长 |
整数 |
Session访问的累计时长 |
URL |
字符串 |
访问地址的URL (不含验证参数) |
访问IP |
字符串 |
客户端的请求IP |
Referer |
字符串 |
访问页面上一个页面地址 |
再将相关数据进行数据切分,分为训练集和测试集,训练集用来进行模型的训练,测试集进行模型的检测。之后将检测达到预期的模型进行保存。
参数类别 |
具体值 |
说明 |
LSTM层数 |
2层 |
双向LSTM,增强序列理解能力 |
隐藏单元数 |
64 |
平衡模型容量和计算效率 |
序列长度 |
20 |
每个输入序列的日志条目数 |
批量大小 |
32 |
训练时的批次大小 |
优化器 |
Adam |
自适应学习率优化算法,引入类似动量,计算所需资源少 |
激活函数 |
Tanh |
Tanh:输出范围(−1, 1),是零中心的。收敛速度通常比Sigmoid快。Tanh会将所有输入都映射到(−1, 1)区间,不具备稀疏性,输出不会爆炸 |
学习率 |
0.001 |
Adam默认学习率 |
序列总量 |
2500 |
访问的session总数 |
访问日志总量 |
12700 |
爬虫或者正常用户访问日志总量 |
正常用户日志总量 |
9900 |
用户访问日志总量 |
正常用户序列总量 |
1700 |
正常访问的session总数 |
爬虫序列总量 |
800 |
爬虫访问的session总数 |
爬虫识别总数 |
790 |
模型识别出的爬虫数量 |
爬虫识别正确率 |
98.75% |
模型识别正确率 |
8. 规则库机制
规则库主要存储一些人工总结的规则,这些规则可以快速的作为一种策略,部署上线,快速地实现对模型效果的补充。规则库解决了下面问题:
1) 复合条件问题,允许多个子条件的逻辑与和或运算。
2) 规则覆盖和冲突问题,每次添加规则的时候,需要与已经存在规则进行比较检测相关冲突。
3) 规则扫描的加速,需要构建一个值到规则的索引,从而加速相关规则的检索。具体可以参考哈希表或者B+树这样的索引。
9. 黑白名单机制
黑名单和白名单的机制[5]是对以上逻辑的补充,如果一个IP或UA,需要强制加白或者加黑,且需要立即生效,可以使用黑白名单。需要注意以下问题:
1) 黑白名单的优先级最高,白名单高于黑名单。
2) 如果黑白名单数据量过大,需要使用哈希表进行索引。
3) 黑白名单通常有时效性,这个表单需要进行定制跟新。
10. 结束语
通过上述的机制,可以屏蔽大部分的爬虫,经过相关实践,也达到了预期的效果,屏蔽了95%以上的爬虫,尤其是恶意爬虫。