nginx防爬虫必须组合ua拦截+限流+robots.txt+白名单兜底,否则易漏拦或误杀;if匹配ua须置于server块顶层,不可嵌套location内,空ua需用= ""单独匹配,robots.txt须用location = /robots.txt精确配置。

直接结论:Nginx 防爬虫不能只靠 UA 黑名单,必须组合 use-agent 拦截 + 限流 + robots.txt 控制 + 白名单兜底,否则要么漏拦、要么误杀。
if ($http_user_agent ~* "Scrapy") 必须放在 server 块顶层
Nginx 的 if 在 location 内部是“伪生效”——它可能被后续配置覆盖,或因执行顺序异常而跳过。官方明确不推荐嵌套使用。
- 正确位置:紧贴
server {下方,listen和server_name之后,所有location之前 - 错误写法:
location /api { if ($http_user_agent ~* "curl") { return 403; } }—— 这条规则大概率被忽略 - 大小写处理用
~*(不区分),避免漏掉python-urllib和Python-urllib - 空 UA 要单独匹配:
if ($http_user_agent = "") { return 403; },不能用正则
robots.txt 返回内容必须用 location = /robots.txt 精确匹配
写成 location /robots.txt 会意外匹配 /robots.txt.bak 或 /robots.txt/xxx,导致返回错误内容甚至泄露路径。
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
- 必须加等号:
location = /robots.txt - 设 MIME 类型:
default_type text/plain;,再补一句add_header Content-Type "text/plain; charset=UTF-8";更保险 - 换行只能用 LF(\n),Windows 的 \r\n 会让部分爬虫解析失败
- 顺序很重要:若要只屏蔽百度、搜狗,其他放行,必须把具体 UA 放前面,最后才是
User-Agent: *,否则 * 会提前终止匹配
limit_req 是防高频爬虫的核心,burst 和 nodelay 要按场景选
单纯封 UA 只能拦住“懒爬虫”,真正消耗资源的是每秒几十次请求的自动化脚本。这时候 limit_req 才是主力。
- 定义区要放
http块:limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=5r/s;($binary_remote_addr比$remote_addr节省内存) - 在
location中启用:limit_req zone=ip_limit burst=10 nodelay; -
burst=10表示允许瞬时最多 15 次请求(基础 5 + 缓冲 10),nodelay让这 10 次立刻处理,不排队;不加它就会延迟响应,影响真实用户 - 登录接口建议
burst=0,彻底禁止连试;静态资源可设rate=100r/s防止页面加载卡顿
白名单比黑名单更可靠,尤其对监控和搜索引擎
盲目封禁含 bot、spider 的 UA,会直接阻断 Googlebot、Applebot、Zabbix、Prometheus 等合法流量,后果比爬虫还严重。
- 先建白名单变量:
map $http_user_agent $is_allowed_ua { default 0; "~*Googlebot|Bingbot|YandexBot|Applebot|Twitterbot|Github-Hookshot|GitLab-CI|Zabbix|Prometheus" 1; } - 再结合拦截:
if ($is_allowed_ua = 0) { if ($http_user_agent ~* "(Scrapy|Python-urllib|HeadlessChrome)") { return 444; } } - 注意:两个
if嵌套在 Nginx 里是允许的,但仅限于这种“先查白名单、再查黑名单”的线性判断 -
return 444比403更干净(不发任何字节),但调试期建议先用403,避免 curl 报 “Connection reset” 无法定位问题
最易被忽略的一点:所有 UA 拦截规则都必须配合日志字段,否则你根本不知道谁被拦了、为什么拦。至少加 $http_user_agent 到 log_format,不然出了问题只能盲猜。










