直接回答:先去访问日志里按 UA 和 IP 统计请求量,找出占比最大的那一个;如果它集中在动态页面(首页、搜索页、分页、带参数的 URL)并且请求间隔很匀,基本就是爬虫。限的顺序是:先限「请求量最大、又不带来搜索收录」的那一个,先限速、不要先封禁;观察半小时仍压不下来,再考虑封 UA 或封 IP。
下面是具体做法。
uptime
top -b -n1 | head -20
vmstat 1 5
iostat -xz 1 3MySQL 侧:
SHOW FULL PROCESSLIST;
SHOW GLOBAL STATUS LIKE 'Threads_running';判断方法很简单:
Web 服务器如果是 Nginx,确认访问日志格式是 combined(默认就是),下面命令才有意义。
按 UA 统计请求数:
awk -F'"' '{print $6}' access.log | sort | uniq -c | sort -rn | head -30combined 格式用双引号切开后,第 6 段就是 User-Agent。
按 IP 统计:
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20按小时看请求分布,确认是不是集中在某个时间段:
awk '{print substr($4,2,14)}' access.log | sort | uniq -c | tail -24按路径看,判断它是在抓静态资源还是反复请求动态页面:
awk -F'"' '{print $2}' access.log | awk '{print $2}' | sort | uniq -c | sort -rn | head -30UA 可以伪造,不能只凭 UA 下结论。 至少对请求量靠前的 IP 做一次反查:
ip="1.2.3.4"
host=$(dig +short -x "$ip" | head -1 | sed 's/\.$//')
echo "$host"
dig +short "$host" A如果正查返回的地址里包含这个 IP,才算前向确认通过。以 Googlebot 为例,只看到 Googlebot 字样不够,要做这一步;不通过的基本就是伪装。
来源 | UA 常见片段 | 是否影响搜索收录 | 处理建议 |
|---|---|---|---|
Googlebot |
| 是 | 不要限,用 Search Console 调抓取速度 |
Bingbot |
| 是 | 同上 |
各类 AI 训练、答案引擎爬虫 |
| 不是传统搜索收录 | 可以限速 |
未知高频 UA | 无固定特征 | 无 | 先看 IP 和行为,再限速或封禁 |
选取顺序:
为什么先限速不封禁:封 UA 会被改 UA 的爬虫绕过,也容易误伤;限速能把源站压力压下来,同时保留被 AI 搜索引用的可能。这个取舍要自己权衡,但不要相信「封掉就完全不影响任何曝光」这种说法。
User-agent: GPTBot
Disallow: /
User-agent: CCBot
Disallow: /
User-agent: Bytespider
Disallow: /要清楚它的边界:robots.txt 是约定,没有强制力。遵守的爬虫会停,不遵守的照样抓。Crawl-delay 只有部分爬虫支持,Google 明确不支持,AI 爬虫是否支持也不确定,不能把它当限流手段。真正的限流在服务器层。
思路是:命中指定 UA 的请求,用「IP + 限速桶」计数;其他 UA 的 key 为空字符串,Nginx 不计入,等于不限。
# 放在 http 块
map $http_user_agent $ai_bot_key {
default "";
~*GPTBot $binary_remote_addr;
~*ClaudeBot $binary_remote_addr;
~*CCBot $binary_remote_addr;
~*PerplexityBot $binary_remote_addr;
~*Bytespider $binary_remote_addr;
}
limit_req_zone $ai_bot_key zone=ai_bots:10m rate=10r/m;
limit_req_status 429;
limit_req_log_level notice;# 放在 server 块
server {
listen 443 ssl http2;
server_name example.com;
location / {
limit_req zone=ai_bots burst=5 nodelay;
try_files $uri $uri/ /index.php?$args;
}
}含义:每个命中 UA 的 IP 每分钟 10 个请求,允许 5 个突发。先从小流量开始,比如 rate=30r/m,观察后再收紧。
改完必须测:
nginx -t && nginx -s reload
curl -A "GPTBot" -I https://example.com/
curl -A "Mozilla/5.0" -I https://example.com/第二条不能被限,否则说明 key 写错了。
对确认不需要的 UA,可以在 server 级直接返回:
map $http_user_agent $deny_bot {
default 0;
~*Bytespider 1;
~*MJ12bot 1;
}
server {
if ($deny_bot) {
return 403;
}
}if 里只写 return 是 Nginx 官方认可的用法;不要在 if 里写 rewrite、proxy_pass 这类指令。
按 IP 限制并发连接数,挡住单 IP 的高并发:
# http 块
limit_conn_zone $binary_remote_addr zone=perip:10m;
# server 块
limit_conn perip 20;如果源站前面有 CDN 或 WAF,优先在 CDN 侧按 UA、IP、频率配置规则,别让请求打到源站再拦。此时 Nginx 里要拿到真实客户端 IP,需要正确配置可信代理,否则 $binary_remote_addr 全是 CDN 节点地址,限速会变成限 CDN。
限速生效后,至少看这几个数:
# 看状态码分布
awk -F'"' '{print $3}' access.log | awk '{print $1}' | sort | uniq -c | sort -rn改配置前先备份文件:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak-$(date +%F-%H%M)回滚就是把备份覆盖回去,nginx -t 通过后再 reload。
wp-cron.php 和 admin-ajax.php:这两个被高频请求时,表现和爬虫很像。如果暂时不想直接写规则,可以先统计一段时间再决定限谁。AumCrawl 做的就是这件事:看哪些 AI 爬虫在抓你的站,并按爬虫分别放行或拦截,介绍页在 aumcreate.com/crawlers。
限流的目标是让正常用户和搜索收录不受影响,而不是把所有 bot 都封掉。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。