很多站长只关心「限速和封 IP」,却忽略了一个更持久的后果:爬虫把大量无价值页面分批抓走后,搜索引擎会让它们被批量收录,稀释站点权重、拖垮抓取配额。本文用 9 个问答讲清 垃圾收录治理的成因、封堵配置与清理流程。
Q:为什么说「被收录」也是一种攻击面?
恶意爬虫批量抓取会留下三类后遗症:
- 索引膨胀:站点真实有价值页面只有 200 个,搜索引擎索引里却出现了 2 万条,大量是带参数的组合 URL。
- 权重稀释:站内链接被垃圾页分摊,核心页面的权重和排名一起被拉低。
- 抓取配额被占:搜索引擎每天给站点的抓取预算是有限的,垃圾页把配额吃掉后,新发布的正常内容反而不被及时收录。
更麻烦的是,这些脏页面是「合规」被收录的,不是被黑的。所以处置成本比清黑链高得多,必须在源头拦,而不是等收录之后再清理。
Q:怎么确认垃圾收录是爬虫造成的?
三步交叉验证,只看索引量会误判:
# 1. 看搜索引擎索引量变化(用 site: 查询或站长平台后台)
# 索引量在短时间内从 200 涨到 2 万 → 典型膨胀特征
# 2. 看服务器日志里被爬取的 URL 形态,统计参数组合数量
grep -iE 'baiduspider|googlebot|bingbot' /var/log/nginx/access.log \
| awk '{print $7}' | awk -F'?' 'NF>1 {print $2}' \
| sort | uniq -c | sort -rn | head -20
# 3. 看这些参数里出现频率最高的键名
grep -iE 'baiduspider' /var/log/nginx/access.log \
| grep -oE '[?&][a-zA-Z_]+=' | sort | uniq -c | sort -rn | head -15
判读方法:如果抓取日志里 Top 参数是 page、sort、keyword、filter 这类筛选与排序键,且 URL 数量呈组合式爆炸,就是索引膨胀。正常蜘蛛抓取应该集中在栏目页、详情页和少量分页,而不是无穷尽的参数组合。
Q:参数页和站内搜索结果为什么会被大量收录?
因为它们在结构上是「合法可访问的独立页面」,蜘蛛只要发现有链接指向,就会当成内容页抓取。三个高发源头:
- 筛选与排序:价格从低到高、按销量排序、颜色筛选,每种组合都是一个新 URL。
- 站内搜索结果页:
/search?q=xxx可以被组合出无限 URL,且内容重复度极高。 - 分页无上限:列表翻到第 500 页仍有链接,蜘蛛会一路抓到底。
根源在于这些 URL 被放进了页面的可抓取链接里。只要链接来自站内且不带 nofollow,蜘蛛就会顺着爬,与页面本身有没有价值无关。
Q:Nginx 层怎么阻止爬虫抓到没价值的 URL?
最有效的一步是在 Nginx 层直接切断参数页对爬虫的响应,比 robots.txt 强得多,因为 robots.txt 只是建议,违规爬虫根本不理:
# 识别搜索引擎官方蜘蛛(按 UA 粗筛)
map $http_user_agent $is_engine_bot {
default 0;
"~*(Baiduspider|Googlebot|bingbot|YisouSpider|Sogou web spider)" 1;
}
# 对筛选、排序、站内搜索路径,蜘蛛只允许抓「无参数」的规范地址
server {
# 带参数的筛选页 / 排序页,蜘蛛一律拒绝
if ($is_engine_bot) {
set $block 0;
if ($arg_sort) { set $block 1; }
if ($arg_filter){ set $block 1; }
if ($arg_price) { set $block 1; }
if ($block = 1) { return 403; }
}
# 站内搜索结果页禁止任何蜘蛛抓取
location ~ ^/search {
if ($is_engine_bot) { return 403; }
# 正常用户照常使用
}
}
注意:if 指令在 Nginx 里有很多限制,多个 if 叠加时只用 set 和 return,不要在里面写 proxy_pass。更稳的替代方案是把这些规则写进 map,用一个变量一次性判定。
Q:robots.txt 和 noindex 该用哪个?
两者作用完全不同,用错会互相抵消:
- robots.txt Disallow:阻止蜘蛛抓取。已经收录的页面不会被移除,而且如果其他站有链接指向,搜索引擎仍可能凭 URL 收录(无内容快照)。
- meta noindex:阻止蜘蛛收录。必须能被抓取到才能读到这个标签,所以写了 noindex 的页面不能同时被 robots.txt 屏蔽。
正确的组合是:
# robots.txt(放在站点根目录)
User-agent: *
Disallow: /search
Disallow: /*sort=
Disallow: /*filter=
Allow: /product/
Sitemap: https://www.example.com/sitemap.xml
<!-- 参数页模板里输出:允许抓取,但明确不收录 -->
<meta name="robots" content="noindex, follow">
选择方法:想要页面彻底从索引里消失,用 noindex 并保持可抓取;想要省抓取配额、页面本来就不需要收录,用 robots.txt Disallow。noindex, follow 中的 follow 要保留,让权重还能顺着页面里的链接传递下去。
Q:canonical 怎么配才真的有效?
canonical 是告诉搜索引擎「这一堆相似 URL 里,哪一个是代表」。三个必须做对的地方:
- 参数页统一指向无参数版本,且目标 URL 必须返回 200,不能指向 404 或跳转链。
- canonical 要绝对地址,写完整域名和协议,不要用相对路径。
- 不要自相矛盾:同一个页面不同参数版本如果各自 canonical 指向自己,等于声明它们都是独立页面,反而助长膨胀。
# Nginx 输出 canonical 的示例(去掉参数与排序键)
set $clean_uri $uri;
add_header Link '<https://www.example.com$clean_uri>; rel="canonical"' always;
更省事的做法是让带参数的 URL 直接 301 到无参数版本,从根上消灭重复 URL,比 canonical 更彻底。代价是牺牲了筛选页的可用性,所以一般只对排序类参数(sort、order)这么做,筛选类保留 canonical。
Q:已经被收录的垃圾页面怎么清理?
清理分四步,顺序不能颠倒,否则旧页面还没掉、新页面又被收:
- 先截流:按上面的配置把参数页对蜘蛛封掉,确保不再产生新的垃圾 URL。
- 改响应码:确定要下线的页面返回 410 Gone(比 404 更快被移除)或 301 合并到对应规范页。
- 提交移除:在站长平台使用「移除 URL / 快速下线」工具批量提交,一次提交有数量上限,优先提交被索引最多的那批,不要一次全提。
- 更新 sitemap:sitemap 里只保留规范 URL,把参数页全部剔除,让搜索引擎重新认识站点结构。
# 收缩抓取面:生成 sitemap 时排除带参数的 URL
grep -vE '\?(sort|filter|page|keyword)=' urls_all.txt > sitemap_urls.txt
wc -l sitemap_urls.txt
经验值:参数页清理的收录下线周期通常需要2 到 8 周,期间索引量会先小幅上升再下降,属于正常现象,不要因为没立刻见效就反复改策略。
Q:怎么限制爬虫的抓取节奏,避免它继续扫?
官方蜘蛛是应该被允许抓取的,我们要管的是抓取速度而不是抓取本身。做法是给蜘蛛单独一个较低频率的限速区:
# 给搜索引擎蜘蛛独立的限速组,把抓取速度压到站内可承受的水平
map $is_engine_bot $bot_key {
1 $http_user_agent; # 同 UA 归到一组,共用配额
0 "";
}
limit_req_zone $bot_key zone=botzone:10m rate=2r/s;
server {
# 蜘蛛请求单独限速:2 请求/秒,突发 10
limit_req zone=botzone burst=10 nodelay;
limit_req_status 429;
}
同时用 Crawl-delay 给出明确建议值(百度与必应支持,Google 不读这条),并通过站长平台的抓取压力调节功能把抓取频次直接降到最低档。这才是治本的做法,比在 Nginx 里硬封蜘蛛更安全,不会误伤 SEO。
Q:还有什么补充建议?
- 先分清是哪一类爬虫造成的。官方蜘蛛造成的膨胀,用 robots 与 canonical 治理;伪冒蜘蛛造成的,用 IP 段校验加行为限速,两者的处置方式完全不同。
- 给站内搜索加上 noindex 是性价比最高的一步。绝大多数站点的索引膨胀都和搜索页有关,一行 meta 标签就能止住最大的那个来源。
- 每季度核对一次索引量与真实页面数的比值。经验阈值:索引量超过真实页面数三倍就要开始排查,别等到几十倍才动手。
- 别急着用 robots.txt 一刀切封蜘蛛。一旦屏蔽了正常抓取,正当竞争页面同样收不进来,SEO 会长期受损,恢复周期比清理垃圾收录长得多。
一句话总结:垃圾收录的本质是「可抓取 URL 太多、有价值 URL 太少」。把抓取面收窄到规范地址,再配合 canonical 与 noindex,索引自然会回到健康水位。