核心摘要
AI 爬虫治理不是维护一份永不过期的 Bot 名单,而是先区分搜索索引、模型训练、实时 AI 输入和用户触发 Agent,再组合机器可读偏好、身份核验、强制控制、日志与内容授权策略。robots.txt 很重要,但 RFC 9309 已明确:它不是访问授权机制。
先按用途分类,而不是按“AI”标签分类
同一运营方可能发布多个 Product Token,因为请求承担不同任务。OpenAI 当前分别使用 GPTBot 表达潜在训练用途、OAI-SearchBot 建立 ChatGPT 搜索索引,并用 ChatGPT-User 处理部分用户触发请求。Anthropic 也区分 ClaudeBot、Claude-SearchBot 与 Claude-User。Google 的 Google-Extended 则是控制用途的 Token,并不是独立 HTTP User-Agent。
| 用途 | 可能价值 | 主要风险 | 首要决策 |
|---|---|---|---|
| 搜索索引 | 搜索发现、链接和摘要 | 抓取负载、不希望展示的片段 | 是否希望该页面可被发现? |
| AI Input / Grounding | AI 答案引用与发现 | 答案替代、内容暴露 | 哪些页面可在请求时使用? |
| 模型训练 | 潜在生态触达 | 长期复用、归因与授权不清 | 是否授权或保留该用途? |
| 用户触发 Agent | 帮用户即时完成任务 | 自动操作、滥用与副作用 | 该路由是否为自动化设计? |
不要仅因爬虫名称中出现“AI”就推断用途。Product Token、用途说明和验证方式都会变化,决策前应查看运营方当前官方文档。
robots.txt 真正保证什么
机器人排除协议规定了爬虫如何选择匹配的 User-agent Group,并应用 Allow、Disallow。最具体的路径匹配优先;同一 Product Token 的多个匹配 Group 需要合并。robots.txt 返回 4xx 时,爬虫可以视为没有规则;因 5xx 或网络错误不可达时,规范要求爬虫在一段合理时间内视为全部禁止。
协议不会验证爬虫身份,也不能保护机密 URL。路径即使被声明 Disallow,没有其他控制时仍可直接访问。不要把秘密路径写进 robots.txt,因为这个文件本身公开可读。
一份按用途区分的策略示例
下面允许已记录的搜索爬虫,拒绝训练爬虫,并把用户触发 Agent 交给应用控制:
User-agent: OAI-SearchBot
Allow: /
User-agent: GPTBot
Disallow: /
User-agent: Claude-SearchBot
Allow: /
User-agent: ClaudeBot
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: *
Disallow: /account/
Disallow: /admin/
通配规则不能替代 /account/ 与 /admin/ 的认证授权。每个子域都要在自己的 /robots.txt 发布策略;部署后应测试状态码、媒体类型、编码、重定向和规则匹配。
分开处理爬取偏好与索引控制
robots.txt 控制爬取,不负责所有下游用途。搜索引擎的 noindex、摘要和缓存指令有各自语义。noai、noimageai 或厂商自定义字段并不属于 RFC 9309,不能写成所有爬虫都会遵守的统一标准。
Content Signals 是一种扩展,可分别表达 search、ai-input 和 ai-train 偏好。但该项目也明确提醒:自动系统可能忽略这些信号,法院也未必认定它们构成可执行义务。因此,它是策略声明,不是合规证明。
执行命名规则前先核验身份
HTTP User-Agent 是客户端自我声明,恶意爬虫可以复制 Googlebot、GPTBot 或任意字符串。运营方提供 IP 列表或反向 DNS 验证方法时,应使用这些机制,并结合请求行为与路由策略。
一条可审计分类记录可以包含:
{
"observed_user_agent": "OAI-SearchBot/1.4",
"claimed_product_token": "OAI-SearchBot",
"verified_operator": "openai",
"purpose": "search",
"route_class": "public_article",
"decision": "allow",
"policy_revision": "crawler-policy-v7"
}
日志不要保留完整 Query String、Cookie、Authorization Header 或私有页面正文。只记录解释决策和识别行为变化所需的最小证据。
构建可强制执行的控制面
可信基础设施负责给出已验证身份和用途分类,应用策略再做确定性决策:
package main
import "fmt"
type Purpose string
const (
PurposeSearch Purpose = "search"
PurposeTraining Purpose = "training"
PurposeAgent Purpose = "agent"
)
type Request struct {
Operator string
ProductToken string
Purpose Purpose
IdentityProven bool
RequestsMinute int
}
func decide(request Request) (string, string) {
if !request.IdentityProven {
return "challenge", "crawler identity is unverified"
}
switch request.Purpose {
case PurposeTraining:
return "deny", "training is not licensed by this policy"
case PurposeSearch:
return "allow", "verified search crawler on public content"
case PurposeAgent:
if request.RequestsMinute > 20 {
return "rate_limit", "user-directed automation exceeded its budget"
}
return "allow_with_application_auth", "route policy still applies"
default:
return "deny", "unknown purpose"
}
}
func main() {
requests := []Request{
{Operator: "openai", ProductToken: "OAI-SearchBot", Purpose: PurposeSearch, IdentityProven: true, RequestsMinute: 4},
{Operator: "openai", ProductToken: "GPTBot", Purpose: PurposeTraining, IdentityProven: true, RequestsMinute: 4},
{Operator: "unknown", ProductToken: "Googlebot", Purpose: PurposeSearch, IdentityProven: false, RequestsMinute: 200},
{Operator: "anthropic", ProductToken: "Claude-User", Purpose: PurposeAgent, IdentityProven: true, RequestsMinute: 27},
}
for _, request := range requests {
action, reason := decide(request)
fmt.Printf("%s/%s -> %s (%s)\n", request.Operator, request.ProductToken, action, reason)
}
}
预期输出:
openai/OAI-SearchBot -> allow (verified search crawler on public content)
openai/GPTBot -> deny (training is not licensed by this policy)
unknown/Googlebot -> challenge (crawler identity is unverified)
anthropic/Claude-User -> rate_limit (user-directed automation exceeded its budget)
生产实现还应加入路由分类、Tenant 边界、滥用信号、紧急旁路,以及短时效的决策缓存。未知客户端不能继承其声称运营方的权限。
各层控制能做什么
| 控制层 | 能解决什么 | 不能证明什么 |
|---|---|---|
robots.txt |
发布路径级爬取偏好 | 身份、授权或实际遵守 |
| Content Signals | 按用途发布内容偏好 | 生态采纳或法律强制力 |
| IP / rDNS 核验 | 提高运营方身份可信度 | 内容最终如何被使用 |
| WAF / CDN 规则 | 阻断或挑战匹配流量 | 所有规避爬虫都被识别 |
| 应用认证 | 控制私有路由与对象 | 公开内容的许可条件 |
| 限流与配额 | 保护服务器容量 | 请求用途或版权状态 |
| 访问日志与分析 | 提供运营证据 | 完整训练数据来源 |
应采用纵深控制,但不要把每个自动客户端都视为攻击者。限流阈值需要根据路由成本和滥用容忍度确定,不能照搬统一数字。
AI Labyrinth 是蜜罐,不是防火墙
Cloudflare 当前将 AI Labyrinth 描述为一组不可见的 nofollow 链接,非合规爬虫可能继续跟随。它记录两类事件:页面已注入迷宫链接,或爬虫进入迷宫。官方文档明确指出,这些 Action 不是 Mitigation,不会直接 Block 或 Challenge 当前请求。
因此,AI Labyrinth 适合做检测和行为情报,不能据此宣称爬虫一定被永久困住、训练集一定被污染,或真实内容已经受到保护。要求拒绝访问时,应同时配置强制执行功能,并通过日志验证效果。
法律与授权边界
技术控制和法律权利有关联,但不能互相替代。欧盟《人工智能法案》对通用目的 AI 模型提供方提出了版权合规政策和训练内容摘要等义务;欧盟《数字单一市场版权指令》第 4 条中的文本与数据挖掘权利保留,则是另一套法律机制。这些规定不意味着每条 robots.txt 规则在所有法域都会自动产生相同法律后果。
不要把尚未终审的诉讼、和解或厂商授权交易写成普遍判例。更可靠的运营记录包括:
- 发布清晰条款和机器可读偏好;
- 标识内容所有者与许可状态;
- 保存策略版本及必要访问证据;
- 提供联系和争议处理流程;
- 针对具体法域取得法律意见;
- 将公开发现与认证数据访问分开。
上线与衡量
先以观察模式运行一个完整业务周期,再决定阻断:
- 盘点路由和数据分级;
- 将当前爬虫 Token 映射到官方用途;
- 在条件允许时验证运营方身份;
- 测量请求量、字节量、状态码、缓存影响、引荐和引用;
- 用历史日志模拟新策略;
- 按路由与用途灰度,并保留回滚开关;
- 对未知高流量客户端和策略漂移告警;
- 运营方修改爬虫契约时重新审查。
成功指标不是“拦了多少 Bot”,而是服务器容量受到保护、预期发现能力保留、误判率可控,并且每个决策都有可解释证据。
常见问题
robots.txt 能阻止 AI 爬虫访问网站吗?
不能。它是爬取偏好协议,不是访问控制。私有数据应依靠认证授权;需要阻断流量时应使用 WAF、CDN 或服务端策略。
网站应该屏蔽所有 AI 相关 User-Agent 吗?
不应该。应分别决定 Search、AI Input、Training 和用户触发 Agent 的策略。全量屏蔽可能让页面退出正常发现渠道,或破坏用户主动发起的工作流。
User-Agent 能识别爬虫身份吗?
不能单独识别。运营方提供 IP 范围或反向 DNS 时应进行核验,并结合行为和路由策略决策。
AI Labyrinth 会阻断或污染爬虫吗?
Cloudflare 将其定义为蜜罐,并明确事件不是 Mitigation。除非有独立测量,否则不要把“永久困住”或“污染训练集”写成保证。
机器可读 Opt-out 一定具有法律约束力吗?
法律效果取决于机制、法域、合同和案件事实。应发布清晰偏好、保留证据,并就可执行权利取得专业法律意见。