某天下午想看看谁在访问,一条数 UA 的命令跑完,前几名全是同一个东西:UA 尾巴上挂着 `meta-externalagent/1.1` 的 Chrome。这台机器从凌晨三点到下午,6075 条请求里有 3675 条来自它,差不多六成,其中 1889 条是 POST。
不是扫描器那种乱撞的请求,它老老实实抓页面,还顺手把页面里的搜索框和社交登录按钮点了一遍,每一次点击都落到 PHP 上。处理办法很轻:nginx 里加一段 map 和一行 limit_req,按 UA 限速,reload 不重启,先把峰值按住再观察。
先数清楚是谁
日志就是宝塔默认的那份 combined 格式,UA 固定在第 6 个引号字段,一条命令足够。
cd /www/wwwlogs
awk -F'"' '{print $6}' littlesheep.cc.log | sort | uniq -c | sort -rn | head -5
输出是这样的(UA 尾巴截断了):
2105 Mozilla/5.0 (Windows NT 10.0 ...) ... (compatible; meta-externalagent/1.1 ...)
1043 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ... (compatible; meta-externalagent/1.1 ...)
320 Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/151.0.0.0 Safari/537.36
256 Mozilla/5.0 (Linux; Android 7.0;) ... (compatible; PetalBot; ...)
前两行是同一个爬虫的两种系统 UA,加上 Linux 和 Edge 两个变体,合起来 3675 条。接着数它干了什么:
grep meta-externalagent littlesheep.cc.log | sed -E 's/.*"(GET|POST) .*/\1/' | sort | uniq -c
# 1786 GET
# 1889 POST
grep meta-externalagent littlesheep.cc.log | sed -E 's/.*\[([^]]+)\].*/\1/' | sort | uniq -c | sort -rn | head -3
# 33 17/Oct/2026:11:35:57 +0800
# 29 17/Oct/2026:11:28:40 +0800
一半以上是 POST,最快的某一秒打了 33 个请求。这两个数字决定了后面该用哪种手段。
它为什么会点按钮
看几条原始行就明白了,请求带 referrer,指向刚刚抓过的页面,落点是主题的接口:
163.181.66.162 ... "POST /wp-admin/admin-ajax.php?action=menu_search HTTP/2.0" 200 1366 "https://www.littlesheep.cc/tag/..." "...meta-externalagent/1.1..."
163.181.66.161 ... "POST /wp-admin/admin-ajax.php?action=search_box HTTP/2.0" 200 1906 "https://www.littlesheep.cc/tag/..." "...meta-externalagent/1.1..."
163.181.66.159 ... "GET /oauth/qq HTTP/2.0" 302 0 "https://www.littlesheep.cc/tag/..." "...meta-externalagent/1.1..."
纯 HTTP 抓取不会 POST 到 admin-ajax,这说明它用的是无头浏览器,页面 JS 真的在跑,菜单搜索组件触发一次就发一个请求,社交登录链接被挨个访问。
代价也在这里。Cache Enabler 和边缘缓存都只缓存 GET 的 HTML,POST 一律回源进 PHP-FPM,在这台 2G 内存的机器上,每条 POST 都是实打实的 CPU 和内存。所以"页面缓存开着就没事"这个假设不成立。
三种手段,边界不一样
robots.txt 管的是抓取意愿,对守规矩的爬虫有效。Meta 的文档里 meta-externalagent 明确按 robots 的 token 走,但 facebookexternalhit 有豁免,用于链接预览的那部分会绕过 robots,写规则前先分清这两个名字,否则分享卡片会跟着一起死。
nginx 403 把请求直接归零,代价是 Meta 那边的收录和曝光。名单式拦截还有个老问题,爬虫换 UA 就漏了。
limit_req 管速率不管总量,它防的是"一秒 33 个请求"这种把 PHP-FPM 打满的瞬间。这台机器上我选这个先上,可逆、不误伤、不用赌爬虫会不会遵守规则。
配置怎么写
http 块里加 map 和 zone,放进 nginx.conf 的 http 段:
map $http_user_agent $bot_rate_key {
default "";
"~*meta-externalagent" "meta-externalagent";
"~*PetalBot" "petalbot";
"~*DotBot" "dotbot";
}
limit_req_zone $bot_rate_key zone=bot_rate:10m rate=1r/s;
limit_req_status 429;
站点 server 块里启用:
limit_req zone=bot_rate burst=5 nodelay;
三个细节值得说清楚。
key 用 UA 而不是 `$binary_remote_addr`,因为站点在阿里云 ESA 后面,源站日志里那一串 163.181.x 是节点 IP,按 IP 限速等于把当天所有访客塞进同一个桶,一个爬虫就能把真人一起拖下水。
`default ""` 让普通访客拿到空 key,nginx 文档的原话是 requests with an empty key value are not accounted,空 key 不进桶,正常浏览一点不受影响。
三个 UA 变体映射到同一个值,是为了让 Windows、Mac、Linux 三个字符串共用一个桶,否则它开四个无头浏览器就等于绕过限速。`rate=1r/s 配 burst=5`,允许 6 个瞬时请求,之后一秒放一个,超出返回 429,比默认的 503 更好认。
验证
改完先测配置,再 reload:
/www/server/nginx/sbin/nginx -t && /www/server/nginx/sbin/nginx -s reload
绕过 CDN 直连源站,用爬虫 UA 连发 20 次:
BOT="Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... (compatible; meta-externalagent/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler))"
for i in $(seq 1 20); do curl -sk -o /dev/null -w "%{http_code} " \
--resolve www.littlesheep.cc:443:127.0.0.1 -A "$BOT" https://www.littlesheep.cc/robots.txt; done
# 200 200 200 200 200 200 200 200 200 200 200 429 429 429 429 429 200 429 429 429
前面 11 个放过去,后面开始 429,中间那个 200 是令牌补回来的。换成浏览器 UA 同样连发 20 次,20 个 200,说明真人没被误伤。error log 里也会留下痕迹:
[error] limiting requests, excess: 5.273 by zone "bot_rate" ... request: "GET /robots.txt"
再走 ESA 并发压一遍,15 并发打 30 次:6 个 200、24 个 429。紧接着用浏览器 UA 请求同一个带参数的 URL,返回 200、`x-site-cache-status: MISS`,429 没被边缘缓存留下来,这点很重要,否则一个爬虫能把错误页钉在 CDN 上给所有人看。
坑和回滚
图片、js、css 的 access_log 在宝塔默认配置里指向 `/dev/null`,所以日志里几乎全是动态请求,想统计图床流量得去监控报表里找。
限速压不住总量。这个爬虫日均大概 0.1 请求每秒,1r/s 的桶平时根本碰不到,真正减少请求要靠 robots.txt 声明或者直接 403,限速只是防止它突然加速。
Meta 的 UA 会跟着 Chrome 版本变,日志里同时有 145 和 151,所以用 `~*` 正则匹配关键词,别写完整字符串。
宝塔面板改站点配置会重写 vhost 文件,手工加的这段容易丢,稳妥做法是放进 vhost 里 include 的 extension 目录,单独一个 conf 文件。
回滚就是还原两个备份再 reload,改之前都留了时间戳:
cp /www/server/nginx/conf/nginx.conf.bak-20261017-123338 /www/server/nginx/conf/nginx.conf
cp /www/server/panel/vhost/nginx/littlesheep.cc.conf.bak-20261017-123338 /www/server/panel/vhost/nginx/littlesheep.cc.conf
/www/server/nginx/sbin/nginx -t && /www/server/nginx/sbin/nginx -s reload
现在状态是限速生效、爬虫仍在、首页 0.099 秒,error log 里开始出现 429 记录。这台机器前阵子 mysqld 被 OOM 杀了 5 次,省下的每条 PHP 请求都算数,那次的排查过程写在 819 那篇 里。
日志里怎么把假 IP 换回真访客,684 讲得更细;要更硬的拦截,396 里的 XML-RPC 和登录爆破那套可以一起上。
你的日志里排第一的是谁?把 awk 那行的输出贴出来看看。



![[教程][服务器]在阿里云服务器上卸载AliYunDunMonito(阿里盾)-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2025/12/114612929920251229005735.png)

![[免费][教程]子比主题美化,优化教程-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2026/09/3b06fd6a0520260920160148.webp)
![[免费][插件]将WordPress图片上传到LskyPro蓝空图床的插件-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2026/09/b9e1998d8420260920160152.webp)

![[教程][笔记]Centos7宝塔下安装ImageMagick,无法安装webp扩展解决办法-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2026/09/de103868d420260920155615.webp)
![[资源][教程]AI SEO - WordPress插件-小绵羊的小窝](https://www.littlesheep.cc/wp-content/uploads/2026/01/9f396016b220260112151830.png)



暂无评论内容