文章探讨多维筛选功能导致网站爬虫死循环和抓取配额耗尽的问题。作者分析了爬虫陷阱(Spider Trap)和参数爆炸的原因,强调URL规范化的重要性。文章指出,通过规范化URL和合理配置HTTP响应头,可以有效避免无效抓取,提升网站SEO效果。
前阵子给手头一个内容资讯站加了多标签交叉筛选功能,原本打算让读者找资料更方便,没想到上线两周后后台出了怪事。服务器夜间 CPU 使用率莫名其妙窜到 70% 往上,平时秒级收录的新文章,连着一周过去在搜索结果里连个影子都看不到。
排查服务器负载时,我习惯性翻了翻 Nginx 的访问日志。把百度和谷歌的爬虫 UA 过滤出来一看,当时就愣住了。每天两万多次爬虫抓取,有超过八成全在死磕各种组合参数的 URL,像 ?tag=linux&sort=hot&page=1、?sort=hot&tag=linux&page=1、?filter=arch&tag=linux 这种页面被反复爬了几千遍。这就是典型的蜘蛛陷阱(Spider Trap)配合 URL 参数爆炸,直接把全站的抓取配额(Crawl Budget)吃得精光。
这类问题在很多做列表筛选、电商多属性展示、或者带搜索归档的网站上非常常见。这里把我在排查和清理蜘蛛陷阱时踩翻的四个坑记下来,顺便把最终跑通的配置和清洗思路梳理一遍。
坑一:筛选参数没有统一顺序,阶乘级排列组合把抓取配额啃光
很多开发者觉得前端页面上只有三四个筛选条件,不至于制造太大的麻烦。但数学规律不会骗人。假设页面有四个可选筛选项,一旦没有做固定排序,仅这四个参数的不同排列组合就有 4 的阶乘共 24 种写法。如果每个筛选项还可以多选两三个值,再加上分页参数,一个原本只有几百篇文章的栏目,可以在几小时内裂变出几万甚至几十万个独立的 URL 地址。
爬虫抓取网页时默认把每个不同的 URL 当作新资源来处理。百度的 Baiduspider 和谷歌的 Googlebot 每天给每个站点的抓取预算是有上限的。当爬虫发现你的网站源源不断产生这种新 URL 时,它会投入大量算力去尝试抓完,直接导致真正有价值的新文章、修改后的旧页面根本排不上抓取队列。
解决这个问题的关键在 URL 规范化(URL Canonicalization)。不管访客或者脚本以什么顺序点击参数,服务器都必须把参数按照固定的字典顺序组织起来。
如果是在 Nginx 层面处理,可以用一段配置把乱序的多参数请求重定向到规范地址:
# 伪静态规则中对常见的乱序参数做 301 规范化
# 示例:检测到未排序参数时重定向到标准字典序
location /category/ {
# 过滤掉多余的空参数,避免 ?filter=&sort= 这种无意义后缀
if ($args ~* "^(.*)&([a-z_]+)=&(.*)$") {
set $cleaned_args $1&$3;
rewrite ^(.*)$ $1?$cleaned_args? permanent;
}
}
更彻底的办法是在后端应用框架的中间件里做处理。当收到带筛选参数的请求时,先读取所有 query 参数名,按字母升序排序,剔除空值与默认值(比如 page=1 或 sort=default 本身没意义就直接删掉)。如果当前请求的 query 字符串跟排序后的标准字符串不一致,立刻返回 301 永久重定向到标准 URL。
这样无论外界怎么拼凑参数,爬虫碰壁一次拿到 301 之后就会收敛,不会把重复组合当作新页面无限往下钻。
坑二:盲信 rel="canonical",以为加了规范标签就能高枕无忧
这是很多搞 SEO 的同学最容易陷入的误区。发现 URL 参数满天飞之后,第一反应通常是在页面 <head> 区域里塞一行规范标签:
<link rel="canonical" href="https://www.llbbs.cn/category/linux" />
大家以为搜索引擎看到这个标签就会心领神会,不再抓取那些加了参数的页面。但实际上,rel="canonical" 的作用范围是索引和权重聚合,根本不是抓取拦截。
搜索引擎的蜘蛛要读到你的 canonical 标签,前提是必须先发起一次完整的 HTTP 请求,耗费服务器带宽把整张页面的 HTML 代码下载下来,放进解析管道里跑一遍。换句话说,几十万个带参数的冗余页面,虽然最终可能不会出现在搜索索引库里,但它们该消耗的服务器带宽、CPU 计算资源以及爬虫抓取配额,一点都没少花。
面对深层多维筛选,要保住抓取配额,必须在链接入口和 HTTP 协议头上截断:
第一,对那些纯属辅助浏览的复合筛选页,在 HTTP 响应头里直接输出 X-Robots-Tag: noindex, follow。这比单纯依赖 HTML 里的 canonical 更明确地告诉爬虫不要索引当前参数结果。
第二,改写前端渲染逻辑。核心主分类保留标准的 <a href="/category/linux"> 标签让爬虫抓取,而多重交叉筛选(例如“价格区间+颜色+尺寸+排序”)改用前端异步请求或者无 href 的点击事件。爬虫沿着 DOM 树抓取时找不到继续分裂的 a 标签入口,参数爆炸自然在源头上被掐断。
坑三:robots.txt 写得太奔放,一刀切写成 Disallow: /? 导致有效收录陪葬
吃过参数爆炸的亏之后,有人脾气上来了,直接去根目录改 robots.txt,加了一句极其凶残的规则:
User-agent: *
Disallow: /*?*
这句规则的意思是:只要 URL 里带问号,一律禁止爬虫访问。
这样写的下场往往是灾难性的。许多网站的文章列表分页就是用 ?page=2、?p=3 实现的,有些电商和知识库的核心文档用到了查询参数 ?id=1024。把所有问号全部拦住之后,爬虫不仅无法爬取翻页后面的深层内容,连原本已经积累了权重的老带参数 URL 也会因为无法验证内容而在搜索控制台里报错,最终连带正常收录一起断崖式下跌。
更稳妥的做法是精准拦截已知的冗余参数名,把白名单和黑名单分开写。例如只拦截明确引发爆炸的排序、过滤与标签多选参数:
User-agent: *
# 允许正常文章翻页
Allow: /*?page=[0-9]+$
Allow: /*?p=[0-9]+$
# 精确拦截容易引发排列组合的筛选与排序参数
Disallow: /*?*sort=
Disallow: /*?*order=
Disallow: /*?*filter=
Disallow: /*?*price=
Disallow: /*?*tag_group=
# 拦截任何包含两次以上 & 连接符的深层参数组合
Disallow: /*?*&*&*
写完规则后,建议立刻在 Google Search Console 的“robots.txt 测试工具”和百度搜索资源平台的“Robots 检测”里,拿几个真实的翻页 URL 和带参数 URL 跑一遍校验,确认没有误杀核心页面再推上线。
坑四:日历归档与站内搜索框构成不可逾越的无限深渊
除了多属性筛选,网站上还有两个看起来人畜无害的小功能,极容易演变成隐蔽的蜘蛛陷阱。
第一个是博客和资讯站常用的“文章日历”或“按月归档”小工具。有些模板写得比较随意,侧边栏日历的“上一月”和“下一月”翻页链接没有做边界限制。爬虫顺着 href="/archive/2026/05" 一路往前点,能一直抓到 2000 年甚至 1970 年,反向也能爬到 2050 年。几千个没有任何内容的空白月份页面就这样被生成出来,把爬虫困在时间长河里出不来。
处理办法很简单:只为真正有文章发表的年月生成超链接。对于没有文章的月份,要么完全不展示链接,要么用没有 href 属性的纯文本标签呈现。
第二个是站内搜索。很多网站的搜索结果页是公开可抓取的,比如 /search?keyword=xxx。一旦遇到垃圾采集爬虫或者扫描器往搜索框里灌垃圾关键词,或者某个外链故意引流到你的搜索 URL,百度和谷歌的蜘蛛就会顺藤摸瓜,把几万个搜出来的零结果页面统统当作网站新内容收录进去。这些页面不仅质量极低,容易招致搜索引擎的“低质浅层内容”算法惩罚,还会彻底稀释网站整体的权重。
解决站内搜索的蜘蛛陷阱,必须在 robots.txt 里直接锁死搜索目录,并在搜索结果页强制下发 noindex:
User-agent: *
Disallow: /search
Disallow: /search/
Disallow: /*?s=*
Disallow: /*?keyword=*
同时,在搜索模板的 <head> 区域加上兜底防护:
<meta name="robots" content="noindex, nofollow" />
这样就算外界恶意伪造搜索 URL,爬虫在入口处就会被拦下,即便偶然抓取也不会将其放入索引库。
排查与验证:用一行 Shell 快速定位爬虫的参数黑洞
平时如何确认自己的网站有没有被蜘蛛陷阱缠住?其实完全不需要借助复杂的第三方监控工具,直接在 Linux 终端里查阅近期的 Nginx 访问日志就能一目了然。
运行下面这行命令,统计过去 24 小时内百度和谷歌爬虫最常抓取的带参数路径:
cat /var/log/nginx/access.log | grep -E "(Baiduspider|Googlebot)" | awk '{print $7}' | grep "\?" | cut -d'?' -f1 | sort | uniq -c | sort -nr | head -n 20
输出结果会列出被爬得最频繁的前 20 个基础路径及其抓取次数。如果发现某个明明只有十几篇文章的分支列表页,带参数请求数高居榜首,占比甚至超过了主站正常文章的总和,那就必须立刻把这个路径的 URL 取出来,仔细分析它的 query 参数组合。
把参数排序做规范、对深层无用筛选切断链接跟踪、在 robots.txt 里精准剔除冗余字段。把这几处漏洞补上之后,我在第二天观察 Nginx 日志,爬虫的无效请求量直接从两万多次回落到了几百次以内。随后的两周里,新发布的文章基本都能在当天被正常抓取收录,全站抓取效率恢复了正常水平。
文章标题:多维筛选导致爬虫死循环、海量无效 URL 吃光抓取配额?排查网站蜘蛛陷阱 (Spider Trap) 与参数爆炸我踩过的几个坑
文章链接:https://llbbs.cn/jishujaocheng/226.html
本站文章均为原创,未经授权请勿用于任何商业用途
评论一下?