KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
02 · 抓取:爬虫愿意花多少资源抓你的站 — keel 龙骨
本章目标:讲清「抓取(Crawling)」环节的规则——爬虫以谁的身份来、受什么约束、状态码如何被解读。 验收标准:能写出正确的 robots.txt,并对每个状态码说清它会让爬虫做什么。
本章目标:讲清「抓取(Crawling)」环节的规则——爬虫以谁的身份来、受什么约束、状态码如何被解读。
验收标准:能写出正确的 robots.txt,并对每个状态码说清它会让爬虫做什么。
为什么要单独讲抓取:发现只解决"知道 URL 存在",抓取才解决"真的把内容取回去"。这个环节有两个独立变量——能不能抓(robots 规则)与愿不愿意多抓(抓取预算)。前者是准入,后者是效率。
一、爬虫的身份:User-Agent
爬虫每次请求都会带上 User-Agent(UA),这是你识别它、也约束它的唯一依据。
| 爬虫 | UA 关键字 | 归属 | 执行 JS |
|---|---|---|---|
| Googlebot | Googlebot(Smartphone / Desktop) |
会(二次渲染,见第 03 章) | |
| Bingbot | bingbot |
Microsoft | 有限 |
| Baiduspider | Baiduspider |
百度 | 基本不执行 |
| Sogou | Sogou web spider |
搜狗 | 基本不执行 |
| Bytespider | Bytespider |
字节 | 基本不执行 |
| GPTBot | GPTBot |
OpenAI 训练/索引 | 不执行 |
| OAI-SearchBot | OAI-SearchBot |
OpenAI 搜索 | 不执行 |
| ClaudeBot | ClaudeBot |
Anthropic | 不执行 |
| PerplexityBot | PerplexityBot |
Perplexity | 不执行 |
重要事实:UA 是可以伪造的。 日志里出现自称 Googlebot 的 IP,不代表真是 Google。验证方法是双向 DNS(反解到 *.googlebot.com 再正解回同一 IP),第 05 章细讲。本章只需记住:robots.txt 的规则按 UA 匹配,这是"协约"而非"强制"。
# 用真实 Googlebot UA 请求你的页面(模拟爬虫视角)
curl -s -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
https://www.xxxxxx.cn/learning/ -o /dev/null -w "%{http_code}\n"
二、robots.txt 的语义
robots.txt 放在域名根目录(/robots.txt,不是 /learning/robots.txt)。它由一组 User-agent 段组成,每段下是 Allow / Disallow 规则。
User-agent: *
Allow: /
Disallow: /admin/
Disallow: /api/
User-agent: GPTBot
Allow: /
Disallow: /admin/
Sitemap: https://www.xxxxxx.cn/sitemap.xml
语义要点
| 概念 | 规则 | 常见误解 |
|---|---|---|
| 匹配顺序 | 最长匹配优先,不是先写优先 | 以为写在前面的规则说了算 |
* 通配 |
匹配任意字符,如 Disallow: /*.pdf$ |
以为只在路径末尾生效 |
$ 结尾锚 |
Disallow: /*?$ 屏蔽带空查询串的 URL |
漏写导致参数页被大量抓取 |
| 空 Disallow | Disallow: 等于全部允许 |
与 Disallow: /(全禁)混淆 |
| 多个 UA 段 | 只取最匹配的那一段,不合并 | 以为规则会叠加 |
| 抓取延迟 | Crawl-delay 仅部分爬虫(如 Bing)支持 |
以为 Google 也遵守 |
两个致命的默认值:
- 多个脚手架会生成
Disallow: /的全站禁止 robots.txt,上线时忘了改——这是"其他都对但死活不收录"的经典原因。 - robots.txt 返回 5xx 时,规范的爬虫会保守地停止抓取全站;返回 404 则视为"无限制,随便抓"。所以 robots.txt 必须稳定返回 200。
curl -s -o /dev/null -w "%{http_code}\n" https://www.xxxxxx.cn/robots.txt # 必须 200
curl -s https://www.xxxxxx.cn/robots.txt | grep -i disallow
注意:robots.txt 只是"君子协定",不是访问控制。真要阻止访问请用登录鉴权或
noindex。
三、抓取预算:Crawl Budget 是什么
抓取预算是搜索引擎给每个站点分配的有限抓取配额。官方把它拆成两个变量:
- 抓取速率限制(Crawl Rate Limit):Google 为避免打爆你的服务器而设定的并发/频率上限。
- 抓取需求(Crawl Demand):Google想不想抓——由页面受欢迎程度、内容新鲜度、是否重复决定。
结论:预算 = min(速率上限, 抓取需求)。 小站通常受限于"需求"而非"速率";大站(十万 URL 级)才常撞上速率上限。
什么行为在浪费预算
| 浪费行为 | 具体表现 | 治理 |
|---|---|---|
| 无限参数空间 | ?sort=、?page=、?sessionid= 组合爆炸 |
robots 屏蔽 或 canonical 归一 |
| 重定向链 | http → https → www 两跳 |
sitemap/内链直接指向最终 URL |
| 大量 404/410 | 已删除页面仍在 sitemap 或内链里 | 及时清理 |
| 重复内容 | 同一内容多个 URL | canonical 声明 |
| 慢响应 | 爬虫等超时,配额被空耗 | 优化 TTFB |
| 大量低价值页 | 空标签页、分页深链 | noindex 或 robots 屏蔽 |
# 统计服务端看到的抓取量(详见既有《SEO 收录与优化》第 05 章)
grep -icE 'googlebot' /var/log/nginx/learning.access.log
给中小站的结论:几百到几千页的站点,预算基本不是瓶颈。但"让 sitemap 全部指向 200 的 canonical URL"是任何规模都该守的底线。
四、HTTP 状态码对爬虫的语义
这是抓取环节最容易被忽视、后果最直接的一张表:
| 状态码 | 爬虫的理解 | 正确用法 | 误用后果 |
|---|---|---|---|
| 200 | 正常内容,可索引 | 正常页面 | — |
| 301 | 永久搬家,权重传给新址 | 迁移、规范化 | 链太长浪费预算 |
| 302 | 临时搬家,不传权重 | 短期重定向 | 误当 301 用,权重丢失 |
| 304 | 内容未变,用缓存 | 配合 ETag/Last-Modified | 能省带宽与预算 |
| 404 | 不存在,逐渐从索引移除 | 已删除页面 | sitemap 里混入会降可信度 |
| 410 | 永久删除,更快移除 | 确定不再有的页面 | — |
| 429 | 请求过多,请退避 | 限流时告知爬虫 | 持续 429 会让抓取降速 |
| 503 | 服务暂不可用,会稍后重试 | 维护窗口 | 返回 200 的"维护页"是软 404 |
| 5xx | 服务故障,降低抓取 | 仅真故障时 | 频繁 5xx 会砍预算 |
两个必须记住的语义:
- 302 不传权重,301 传。这是迁移时最容易踩的坑。
- "未登录"必须返回 401/403,不能用 200 返回登录页——否则爬虫会把登录页当成该 URL 的正文收录。SPA 尤其容易犯:所有未知路由回退
index.html且返回 200,产生软 404。
curl -s -o /dev/null -w "%{http_code}\n" https://www.xxxxxx.cn/learning/not-a-real-page/ # 期望 404
五、canonical 与重复内容
同一个内容可能有多个 URL:带尾斜杠/不带、http/https、裸域名/带 www、带跟踪参数。爬虫会认为它们是不同页面。
<link rel="canonical" href="https://www.xxxxxx.cn/learning/courses/tools/lessons/1/">
规则:
- 必须自引用:页面 A 的 canonical 指向自己,而不是首页。
- 与 sitemap、内链三者一致——三处不一致时,搜索引擎会自己猜,结果不可控。
- canonical 是"建议"不是"命令":它无法跨域强制生效,跨域时还需配合 301 与 sitemap。
curl -s https://www.xxxxxx.cn/learning/courses/tools/lessons/1/ \
| grep -oE '<link rel="canonical"[^>]*>'
六、故障速查
| 现象 | 抓取层原因 | 处理 |
|---|---|---|
| 全站都不收录 | robots.txt 是 Disallow: / |
改成 Allow |
| 只抓到首页就停了 | robots 误屏蔽了深层目录 | 检查规则最长匹配 |
| 大量 301 被频繁抓取 | sitemap/内链用了非 canonical URL | 全部指向最终 URL |
| 服务器带宽被爬虫跑满 | 无速率限制/无缓存 | 用 304、限流,观察是否真爬虫 |
| 参数页被海量抓取 | 无限 URL 空间 | robots 屏蔽 + canonical |
| 搜索结果里出现登录页 | 未登录返回了 200 | 改为 401/403 |
七、本章验收
-
robots.txt在根目录、返回 200、Allow 全站、Sitemap 为 https 绝对地址 - 对 301/302/304/404/410/429/503 能各说出一个正确使用场景
- 认识到"未登录/未知路由返回 200"是软 404,已改掉
- 能解释抓取预算的两个变量,并列出你站点在浪费预算的地方
- 确认全站 URL 只有一个 canonical 形式
# 三连检:robots 可访问、未知路径 404、canonical 自引用
curl -s -o /dev/null -w "robots=%{http_code}\n" https://www.xxxxxx.cn/robots.txt
curl -s -o /dev/null -w "404test=%{http_code}\n" https://www.xxxxxx.cn/learning/nope/
curl -s https://www.xxxxxx.cn/learning/ | grep -oE 'rel="canonical"[^>]*'
抓取解决的是"HTML 拿到了"。但拿到的 HTML 里有没有正文,取决于下一章的渲染环节。