网站突然打开变慢、服务器 CPU 和带宽异常飙升,很多站长第一反应是被打了,但排查后却发现不是 DDoS,而是恶意爬虫在日夜不停地抓取页面,把资源耗光了。爬虫类故障和攻击类故障的处理思路不一样:攻击要封,爬虫要限。本文用 8 个问答讲清爬虫把网站抓崩后的完整处理流程,从日志定位到 Nginx 限速屏蔽配置。
Q:怎么判断网站是被爬虫抓崩的,而不是被 DDoS 攻击?
先看访问日志的规律。被 DDoS 打时,请求量大但通常内容单一(大量重复 URL 或非页面请求);被爬虫抓取时,请求会沿着页面链接逐个遍历,表现为大量不同 URL、来源 IP 相对集中、请求间隔规律。用这条命令快速统计日志里访问量最高的 IP:
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20
如果某个或某几个 IP 一天请求了几万甚至几十万次,基本可以确认是爬虫抓取。再抽样看这些 IP 访问了哪些页面:
grep "1.2.3.4" access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head
如果 URL 各不相同、按链接顺序遍历,那就是典型的采集爬虫行为。
Q:确认爬虫 IP 后,应急第一步做什么?
直接封 IP 止血。单个 IP 用 Nginx deny:
# nginx.conf 的 http 或 server 块内
deny 1.2.3.4;
deny 5.6.7.0/24;
改完执行 nginx -s reload 生效。如果爬虫 IP 分散、量大,用 iptables 在系统层封,比 Nginx 更省资源:
iptables -I INPUT -s 1.2.3.4 -j DROP
iptables -I INPUT -s 5.6.7.0/24 -j DROP
iptables-save > /etc/sysconfig/iptables # 持久化(CentOS)
注意:封禁是应急手段,如果爬虫会换 IP,光封 IP 只能缓解,必须配合下面的限速方案。
Q:Nginx 限速防爬虫怎么配?
这是治本的核心配置。在 http 块定义限速区域,然后在 server 或 location 里应用:
http {
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/m;
limit_req_status 429;
server {
location / {
limit_req zone=perip burst=20 nodelay;
}
}
}
参数说明:rate=10r/m 表示每个 IP 每分钟最多 10 个请求,正常用户访问完全够用,采集爬虫会被大量限流;burst=20 允许瞬间突发 20 个排队请求;nodelay 表示突发请求立即处理不排队等待,避免正常用户体验变差;被限的请求返回 429 状态码。如果爬虫频繁请求动态页面,可以只对 PHP/动态接口限得更严格,静态页面放宽,减少误伤。
Q:要不要直接屏蔽常见的恶意爬虫 User-Agent?
可以,这是零成本的补充手段。采集工具、扫描器的 UA 通常有明确特征,直接在 Nginx 里拒绝:
if ($http_user_agent ~* (python-requests|scrapy|curl|wget|java|go-http-client|semrush|ahrefs|mj12bot)) {
return 403;
}
注意两点:一是别把 Baiduspider、Googlebot 等搜索引擎蜘蛛误杀,会直接影响收录;二是 UA 可以伪造,正规恶意爬虫也会伪装成浏览器 UA,所以 UA 黑名单挡住的是低门槛工具,挡不住定向采集,必须和限速配合使用。
Q:用 robots.txt 禁止抓取有用吗?
对合法爬虫有用,对恶意爬虫没用。搜索引擎蜘蛛和遵守规范的采集器会读 robots.txt 并遵守规则;而恶意爬虫、竞品采集器根本不会读这个文件,甚至会把 robots.txt 当成”这里有好内容”的导航图。所以 robots.txt 的定位是规范声明而不是防护手段:用它告诉好爬虫哪些别抓,防坏爬虫靠限速、封禁和 WAF。
Q:爬虫伪装成搜索引擎蜘蛛绕过限速怎么办?
先验证真假,再决定放不放。真蜘蛛的 IP 反查主机名能回到搜索引擎域名,以百度为例:
host 116.179.32.1
# 结果包含 baiduspider/baidu.com 才是真蜘蛛
更严格的做法是正反解双重验证。确认是假蜘蛛后,把它的真实 IP 加入黑名单即可。如果不想自己做验证,可以在 Nginx 里对声明为蜘蛛但 IP 无法反解的请求统一按普通访客限速处理,不给豁免。
Q:封 IP 加限速都上了,爬虫还是不断换 IP 来抓怎么办?
说明对方是有针对性的采集,属于”对抗型”爬虫,手动封 IP 已经跟不上换 IP 速度。这时候的方案升级为:
- 上 CDN / WAF 类产品:把请求先过滤一遍,爬虫特征、频率异常的请求在边缘就被拦截,源站只收干净流量;
- JS 质询:正常浏览器能执行 JS,简单采集脚本不能,开启后能过滤掉大部分初级采集器;
- 降低抓取价值:把高频被抓的列表页做成静态缓存页,爬虫抓到了也只消耗 CDN 缓存,不碰源站数据库。
对于业务上必须防采集的内容(如报价、数据列表),单纯技术手段很难完全防住,可以配合登录可见、动态加载等策略提高采集成本。
Q:还有什么补充建议?
总结一套完整流程:先用日志定位异常 IP,iptables/Nginx 封禁止血;然后配置全局限速(每 IP 限速 + 429)作为长期防护;UA 黑名单做零成本补充;对对抗型爬虫升级到 CDN/WAF + JS 质询。另外建议设置一个简单的监控脚本,每天统计日志中请求量 Top 10 的 IP,超过阈值就告警,比等网站卡了再排查主动得多。爬虫防护的关键不是一次封干净,而是让抓取成本高于收益,对方自然会走。