核心摘要

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 交给应用控制:

text
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 验证方法时,应使用这些机制,并结合请求行为与路由策略。

一条可审计分类记录可以包含:

json
{
  "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 或私有页面正文。只记录解释决策和识别行为变化所需的最小证据。

构建可强制执行的控制面

可信基础设施负责给出已验证身份和用途分类,应用策略再做确定性决策:

go
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)
	}
}

预期输出:

text
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 规则在所有法域都会自动产生相同法律后果。

不要把尚未终审的诉讼、和解或厂商授权交易写成普遍判例。更可靠的运营记录包括:

  • 发布清晰条款和机器可读偏好;
  • 标识内容所有者与许可状态;
  • 保存策略版本及必要访问证据;
  • 提供联系和争议处理流程;
  • 针对具体法域取得法律意见;
  • 将公开发现与认证数据访问分开。

上线与衡量

先以观察模式运行一个完整业务周期,再决定阻断:

  1. 盘点路由和数据分级;
  2. 将当前爬虫 Token 映射到官方用途;
  3. 在条件允许时验证运营方身份;
  4. 测量请求量、字节量、状态码、缓存影响、引荐和引用;
  5. 用历史日志模拟新策略;
  6. 按路由与用途灰度,并保留回滚开关;
  7. 对未知高流量客户端和策略漂移告警;
  8. 运营方修改爬虫契约时重新审查。

成功指标不是“拦了多少 Bot”,而是服务器容量受到保护、预期发现能力保留、误判率可控,并且每个决策都有可解释证据。

常见问题

robots.txt 能阻止 AI 爬虫访问网站吗?

不能。它是爬取偏好协议,不是访问控制。私有数据应依靠认证授权;需要阻断流量时应使用 WAF、CDN 或服务端策略。

网站应该屏蔽所有 AI 相关 User-Agent 吗?

不应该。应分别决定 Search、AI Input、Training 和用户触发 Agent 的策略。全量屏蔽可能让页面退出正常发现渠道,或破坏用户主动发起的工作流。

User-Agent 能识别爬虫身份吗?

不能单独识别。运营方提供 IP 范围或反向 DNS 时应进行核验,并结合行为和路由策略决策。

AI Labyrinth 会阻断或污染爬虫吗?

Cloudflare 将其定义为蜜罐,并明确事件不是 Mitigation。除非有独立测量,否则不要把“永久困住”或“污染训练集”写成保证。

机器可读 Opt-out 一定具有法律约束力吗?

法律效果取决于机制、法域、合同和案件事实。应发布清晰偏好、保留证据,并就可执行权利取得专业法律意见。

延伸阅读

一手来源