AI 爬虫三档授权工程落地:搜索放行、训练拦截、Agent 分层(附脚本)

摘要:2026-09-15,Cloudflare 把"屏蔽 AI 爬虫"这一个开关拆成了 Search / Training / Agent 三个独立控制。本文提出「AI 抓取三档偏好」框架并给出四步落地路径:清点 UA(Python 3.13 日志分档统计)、写下偏好(robots.txt 三档模板)、分层拦截(CDN + Nginx)、验证生效(robots.txt 体检脚本)。附公开站点抽查实测结果与 6 组 FAQ。仅用标准库,无需额外依赖。

文章目录

    • 一、问题背景:一个开关管两种用途的时代结束了
      • [1.1 混合用途爬虫已经占了三成以上的验证流量](#1.1 混合用途爬虫已经占了三成以上的验证流量)
      • [1.2 为什么"一键屏蔽 AI 爬虫"会误伤搜索](#1.2 为什么"一键屏蔽 AI 爬虫"会误伤搜索)
      • [1.3 本文解决什么,适合谁](#1.3 本文解决什么,适合谁)
    • [二、命名框架:AI 抓取三档偏好](#二、命名框架:AI 抓取三档偏好)
      • [2.1 三档的定义与代表 UA](#2.1 三档的定义与代表 UA)
      • [2.2 一个容易搞混的点:声明层的 token 不等于日志里的 UA](#2.2 一个容易搞混的点:声明层的 token 不等于日志里的 UA)
      • [2.3 落地四步](#2.3 落地四步)
    • 三、环境准备
      • [3.1 版本与依赖](#3.1 版本与依赖)
      • [3.2 目录结构](#3.2 目录结构)
    • [四、第一步:清点 UA ------ 先知道自己被谁抓](#四、第一步:清点 UA —— 先知道自己被谁抓)
      • [4.1 从访问日志算三档抓取账](#4.1 从访问日志算三档抓取账)
      • [4.2 实测输出与三个读法](#4.2 实测输出与三个读法)
      • [4.3 日志里看不到的部分](#4.3 日志里看不到的部分)
    • [五、第二步:写下偏好 ------ robots.txt 三档模板](#五、第二步:写下偏好 —— robots.txt 三档模板)
      • [5.1 三档模板(按需删减,不要照抄全部)](#5.1 三档模板(按需删减,不要照抄全部))
      • [5.2 分档不只有"全拦/全放":路径级 Allow](#5.2 分档不只有"全拦/全放":路径级 Allow)
      • [5.3 llms.txt 能做什么、不能做什么](#5.3 llms.txt 能做什么、不能做什么)
    • [六、第三步:分层拦截 ------ CDN 与源站](#六、第三步:分层拦截 —— CDN 与源站)
      • [6.1 CDN 层:三档控制与那个真实陷阱](#6.1 CDN 层:三档控制与那个真实陷阱)
      • [6.2 源站层:Nginx 按 UA 分档](#6.2 源站层:Nginx 按 UA 分档)
      • [6.3 为什么两层都要做](#6.3 为什么两层都要做)
    • [七、第四步:验证生效 ------ 三档体检](#七、第四步:验证生效 —— 三档体检)
      • [7.1 体检脚本](#7.1 体检脚本)
      • [7.2 抽查 5 个公开站点(2026-09-17 实测)](#7.2 抽查 5 个公开站点(2026-09-17 实测))
      • [7.3 最常见的三类写错](#7.3 最常见的三类写错)
    • 八、三档配置对照表
      • [8.1 配置对照](#8.1 配置对照)
      • [8.2 收敛成三个判断](#8.2 收敛成三个判断)
    • 九、适用边界与风险提示
      • [9.1 适用场景](#9.1 适用场景)
      • [9.2 不适用与风险](#9.2 不适用与风险)
    • 十、FAQ
    • 十一、总结

一、问题背景:一个开关管两种用途的时代结束了

"要不要屏蔽 AI 爬虫"这个问题,在过去两年一直是个单选题:要么全放,要么全挡。而这两年里,站长的实际处境是------搜索流量不能丢,但也不想白白被拿去训练

1.1 混合用途爬虫已经占了三成以上的验证流量

按 Cloudflare 在 2026-09-15 发布公告时给出的口径:混合用途爬虫(一只爬虫同时为搜索索引和模型训练抓取内容)占其网络验证爬虫流量的 36.6%,已经是单一最大类目。

同一天公布的两组对比数字更说明问题:

站点行为 占比
屏蔽搜索爬虫的站点 不足 1%
限制 AI 训练的站点 17%

也就是说:绝大多数站点想要搜索,但有近五分之一的站点想退出训练------需求早就分层了,只是过去没有工具把这两件事分开表达。

1.2 为什么"一键屏蔽 AI 爬虫"会误伤搜索

在旧的控制方式下(例如 Cloudflare 已弃用的 "Block AI Bots" 开关),选择屏蔽会同时影响搜索抓取。原因在于爬虫本身没有按用途拆开:

  • GooglebotBingbotApplebot 这类混合用途爬虫,一只同时干两件事;
  • 一旦你把它们整体挡住,搜索收录会一起掉

这也是 Cloudflare 在公告里反复强调的一点:想把训练挡掉、同时保住搜索,就必须用训练档专属的开关 ,而不是整体屏蔽。按官方说明,Selected Block 之后,Applebot、Bingbot、Googlebot 都会一起被挡------这是本轮改造里最容易踩的一个真实陷阱

1.3 本文解决什么,适合谁

本文面向三类人:站点技术负责人 (要落地配置)、SEO/内容团队 (要判断哪些档位该放)、企业架构师(要把爬虫策略纳入 AI 治理范围)。读完你会得到:

  1. 一套可复用的命名框架「AI 抓取三档偏好」;
  2. 一条四步落地路径(清点 → 声明 → 拦截 → 验证),每步都有可直接运行的代码或配置;
  3. 一次公开站点抽查实测 :看别人怎么写的、最常见的错在哪。

二、命名框架:AI 抓取三档偏好

2.1 三档的定义与代表 UA

Cloudflare 这次把爬虫行为拆成三档,这个分类方式本身值得直接复用:

档位 判断依据 代表 UA 对企业的意义
Search 搜索索引 抓取用于建立搜索索引 GooglebotBingbotApplebotOAI-SearchBotClaude-SearchBotPerplexityBot 带来搜索排名与 AI 引用,通常必须放行
Training 模型训练 抓取用于训练或微调模型 GPTBotClaudeBotCCBotMeta-ExternalAgentGoogle-ExtendedApplebot-Extended 内容被无偿使用,按业务意愿决定
Agent 代用户取页 代表用户实时取页(聊天检索、浏览代理) ChatGPT-UserClaude-UserPerplexity-User 有真实用户在场,默认放行更划算

2.2 一个容易搞混的点:声明层的 token 不等于日志里的 UA

这是实操里最常出错的地方,单独拎出来说:

  • Google-ExtendedApplebot-Extended 不是独立爬虫 ,它们是 robots.txt 里的控制位------用来声明"Googlebot / Applebot 抓到的内容,可否用于训练";
  • 所以你在访问日志里永远看不到这两个 UA,"日志里没出现"不等于"没声明";
  • 反过来,日志里出现的 UA 也不一定是官方 token------沿用过期名字是抽查里最常见的问题之一(详见 7.3)。

2.3 落地四步

复制代码
① 清点 UA    → 先知道自己被谁抓:从访问日志算出三档抓取账
② 写下偏好   → robots.txt 三档模板(+ 路径级 Allow 的精细写法)
③ 分层拦截   → CDN 层三档控制 + 源站层按 UA 分流
④ 验证生效   → 用体检脚本回查,确认三档真的按预期生效

顺序不能反。先清点再声明------否则你写的偏好可能根本不是针对真实在抓你的那批 UA。


三、环境准备

3.1 版本与依赖

项目 版本 说明
Python 3.13.12 两个脚本只用标准库re / sys / urllib / collections
访问日志 nginx combined 格式 若用 Apache,改 LINE 正则即可
可选 CDN 控制台 / Nginx 第 3 步的分层拦截

本文所有代码均在 Python 3.13.12 实测通过;代码兼容 3.9+。

3.2 目录结构

text 复制代码
crawler-tier/
├── tier_stats.py       # ① 日志分档统计
├── tier_check.py       # ④ robots.txt 三档体检
├── robots_template.txt # ② 模板
└── access_sample.log   # 测试用日志

四、第一步:清点 UA ------ 先知道自己被谁抓

4.1 从访问日志算三档抓取账

python 复制代码
# tier_stats.py --- 从访问日志算「三档抓取账」(Python 3.13.12)
# 用法:python tier_stats.py access.log
import re, sys
from collections import Counter

TIERS = {                                   # 日志里真实出现的 UA;Google-Extended 不在日志里
    "search":   ["Googlebot", "Bingbot", "Applebot", "OAI-SearchBot", "Claude-SearchBot", "PerplexityBot"],
    "training": ["GPTBot", "ClaudeBot", "CCBot", "Bytespider", "Meta-ExternalAgent"],
    "agent":    ["ChatGPT-User", "Claude-User", "Perplexity-User"],
}
LINE = re.compile(r'"(?P<req>[^"]*)" (?P<status>\d{3}) (?P<size>\d+|-) "[^"]*" "(?P<ua>[^"]*)"')

def tier_of(ua):
    for tier, tokens in TIERS.items():
        for t in tokens:
            if t.lower() in ua.lower():
                return tier, t
    return "human", "browser"

def main(path):
    req, byt, ua_hits, tr_paths = Counter(), Counter(), Counter(), Counter()
    total = total_b = 0
    for line in open(path, encoding="utf-8"):
        m = LINE.search(line)
        if not m:
            continue
        size = int(m.group("size")) if m.group("size").isdigit() else 0
        tier, token = tier_of(m.group("ua"))
        req[tier] += 1; byt[tier] += size; total += 1; total_b += size
        if tier != "human":
            ua_hits[token] += 1
        if tier == "training":
            tr_paths[m.group("req").split()[1]] += 1
    print("总请求 %d,总出流量 %.1f MB\n" % (total, total_b / 1024 / 1024))
    print("%-9s %10s %8s %14s %8s" % ("档位", "请求数", "请求占比", "出流量(MB)", "流量占比"))
    for tier in ("human", "search", "training", "agent"):
        print("%-9s %10d %7.1f%% %14.1f %7.1f%%"
              % (tier, req[tier], req[tier] / total * 100, byt[tier] / 1024 / 1024,
                 byt[tier] / total_b * 100))
    print("\n非人类访问 Top UA:")
    for ua, n in ua_hits.most_common(6):
        print("  %-18s %6d 次" % (ua, n))
    print("\n训练类抓取 Top 路径:")
    for p, n in tr_paths.most_common(4):
        print("  %-28s %6d 次" % (p, n))

if __name__ == "__main__":
    main(sys.argv[1])

4.2 实测输出与三个读法

用一段 12,000 行的访问日志样本(nginx combined 格式,合成样本、非真实站点数据,仅用于演示口径)跑一遍:

text 复制代码
总请求 12000,总出流量 442.0 MB

档位               请求数     请求占比        出流量(MB)     流量占比
human           9040    75.3%          336.4    76.1%
search          1102     9.2%           22.0     5.0%
training        1354    11.3%           77.3    17.5%
agent            504     4.2%            6.4     1.4%

非人类访问 Top UA:
  GPTBot                671 次
  Googlebot             571 次
  ClaudeBot             319 次
  ChatGPT-User          254 次
  CCBot                 237 次
  Bingbot               218 次

训练类抓取 Top 路径:
  /blog/data-boundary             144 次
  /blog/2026-agent-governance     135 次
  /blog/robots-tier               129 次
  /docs/api/auth                  127 次

三个读法

  1. 看请求占比,更要看流量占比。 样本里训练类只占 11.3% 的请求,却吃掉 17.5% 的出流量------因为它抓得更深、单页更大。只按请求数判断"影响不大"会低估成本。
  2. 搜索类"轻"、训练类"重"。 搜索类占 9.2% 请求、仅 5.0% 流量(它抓的是入口页);训练类是深度遍历 ,还偏偏往 /docs/api/auth 这类路径走------这正是"要不要给它全部路径权限"的判断依据。
  3. Agent 档量小但增速快。 样本里只占 4.2%,但它是有真人在场的取页。挡掉它等于挡掉一个正在提问的用户,通常不划算。

4.3 日志里看不到的部分

清点有个盲区:如果 CDN 在边缘就把爬虫挡掉了,请求根本到不了源站,日志里也就没有记录。所以:

  • 只看源站日志,会低估真实的爬虫规模;
  • 结论是:UA 清点必须结合 CDN 侧的日志或统计一起看,两层对不上是常态,不是数据出错。

五、第二步:写下偏好 ------ robots.txt 三档模板

5.1 三档模板(按需删减,不要照抄全部)

text 复制代码
# robots.txt ------ 三档授权模板
# ① 搜索索引:放行。搜索流量与引用都靠这一档
User-agent: Googlebot
Allow: /

User-agent: Bingbot
Allow: /

User-agent: Applebot
Allow: /

# ② AI 搜索引用:放行。它带来引用与回流量
User-agent: OAI-SearchBot
Allow: /

User-agent: Claude-SearchBot
Allow: /

User-agent: PerplexityBot
Allow: /

# ③ 模型训练:按业务意愿决定。下面这组是「拒绝」
#    注意:Google-Extended / Applebot-Extended 是控制位,不是独立爬虫
User-agent: GPTBot
Disallow: /

User-agent: ClaudeBot
Disallow: /

User-agent: CCBot
Disallow: /

User-agent: Meta-ExternalAgent
Disallow: /

User-agent: Google-Extended
Disallow: /

User-agent: Applebot-Extended
Disallow: /

# ④ Agent(代表用户实时取页):默认放行,敏感路径可单独收紧
User-agent: ChatGPT-User
Allow: /

User-agent: Claude-User
Allow: /

User-agent: Perplexity-User
Allow: /
Disallow: /account/

Sitemap: https://www.example.com/sitemap.xml

用本文第 7 节的体检脚本回查这份模板,结果是:search 放行(6/6 命中专属组)|training 整站拦截(6/6)|agent 放行(3/3)------即"搜索放行、训练拦截"这个目标被准确表达了。

5.2 分档不只有"全拦/全放":路径级 Allow

robots.txt 支持在整站拦截之后,再把某些路径单独放开 。本文抽查的 www.theverge.com 就是这种写法(2026-09-17 抓取):

text 复制代码
User-agent: GPTBot
Allow: /

User-agent: Google-Extended
Disallow: /
Allow: /sp/

含义是:其它路径一律不给训练用,但 /sp/ 下的内容可以。这个模式很实用------当法务或业务判断"部分内容可以开放、但归档内容不行"时,不必在"全开"和"全关"之间二选一。

5.3 llms.txt 能做什么、不能做什么

除了 robots.txt,近一年还有个常被提到的 llms.txt。这里需要说清边界,避免误用:

事实
性质 社区提案,不是正式标准------没有 RFC、没有 W3C 背书
作用 用 Markdown 列出站点关键页面与简介,方便模型理解站点结构
局限 是否遵循由各家爬虫自行决定,不像 robots.txt 有较长历史与较广的共识
定位 它是"欢迎来读 "的说明,不是"不许抓"的控制

判断规则很简单:要"拒绝"用 robots.txt;要"说明"才用 llms.txt。把 llms.txt 当成授权开关,是常见误解。

在做企业 AI 可见度的项目里(我们团队在 环曜 AIVO 这条线上做官网语义改造时),实践顺序也是先 robots.txt 把授权边界写清楚、再谈 llms.txt 与页面语义优化------顺序反了会先解决"能不能被读",而把"谁来读、读到什么程度"留成后患


六、第三步:分层拦截 ------ CDN 与源站

6.1 CDN 层:三档控制与那个真实陷阱

Cloudflare 在 2026-09-15 生效的改动里,有几个直接可用的能力:

变化 内容
一个开关拆三个 Search / Training / Agent 三个独立控制替换原 Block AI Bots
偏好同步 Bot Preference Sync 取代 Managed Robots.txt:设一次偏好,同步到所有支持的爬虫
可问责爬虫 提出 Accountable 四项要求:robots.txt 可退训练、可退 AI 摘要、提供 URL 级可见性、承诺退出训练不影响搜索排名;Apple / Google / Microsoft 已达标或给出时间表
新域名预设 变现型站点:搜索放行、训练拒绝、广告页挡 Agent;非变现型站点:三档全放行
待跟进 Bingbot 预计 2027 年初支持

陷阱就藏在"Block"这个选项里 :选了 Block,Applebot / Bingbot / Googlebot 会被一起挡掉,搜索也一起没了。要"留搜索、退训练",必须用训练档专属的开关,而不是整体屏蔽。

另外,Cloudflare 也在参与 IETF 的 ai-prefs 规范制定------目标是把"AI 访问偏好"做成可移植的标准化表达。也就是说,现在是各家用各家开关的过渡期,配置时要抬头看一眼标准进展。

6.2 源站层:Nginx 按 UA 分档

CDN 不做全量覆盖(或你根本没上 CDN)时,源站是最后一道。下面这段把三档分流:搜索类与 Agent 类放行、训练类限速,并把档位写进日志字段供第 4 步统计。

nginx 复制代码
# /etc/nginx/conf.d/tier.conf ------ 三档 UA 分流(Nginx 1.24+)
# ⚠️ 本文环境未安装 Nginx,以下片段按官方指令手册编写,未实机验证;
#    上线前务必先跑 nginx -t,并按你的版本核对指令可用范围

# 1) 分档:把 UA 映射成 0/1/2/3
map $http_user_agent $crawler_tier {
    default   0;                                                                    # 0 = 普通用户
    "~*(Googlebot|bingbot|Applebot|OAI-SearchBot|Claude-SearchBot|PerplexityBot)" 1; # 1 = 搜索
    "~*(GPTBot|ClaudeBot|CCBot|Bytespider|Meta-ExternalAgent)"                   2; # 2 = 训练
    "~*(ChatGPT-User|Claude-User|Perplexity-User)"                                3; # 3 = Agent
}

# 2) 只为训练类生成限流键:非训练类的键为空字符串,不计入限流
map $crawler_tier $train_key {
    default "";
    2       $binary_remote_addr;
}
limit_req_zone $train_key zone=train_zone:10m rate=6r/m;

# 3) 日志格式里带上档位字段,交给第 4 步的脚本统计
log_format tiered '$remote_addr [$time_local] "$request" $status $body_bytes_sent '
                  '"$http_user_agent" tier=$crawler_tier';

server {
    listen 443 ssl http2;
    server_name www.example.com;

    access_log /var/log/nginx/access.log tiered;   # 档位在字段里,不必拆多份日志

    limit_req zone=train_zone burst=3 nodelay;     # 训练类限速(非一律 403)

    location / {
        try_files $uri $uri/ /index.html;
    }

    # 训练类不给账号与内部接口路径
    location ~ ^/(account|docs/api)/ {
        if ($crawler_tier = 2) { return 403; }
        try_files $uri $uri/ /index.html;
    }
}

配置要点三条:① 先分档再决策 ,而不是一条条 UA 写 allow/deny;② 训练类限速而不是一律 403 ------如果你只是不想被高频抓,限速更温和也更少见争议;③ 把档位写进日志字段tier=$crawler_tier),不然第 4 步没法核算。

6.3 为什么两层都要做

优点 局限
robots.txt 公开、可审计、被广泛遵循 是请求,不是墙:不阻止被索引、不保护内容、不跨子域生效
CDN 控制 在边缘就拦下,请求不会到达源站 各家开关口径不一,且拦截发生在源站之前,robots.txt 里看不到
源站拦截 完全可控、可自定义分级 请求已到达源站,省不下带宽

结论:robots.txt 管"声明",CDN 与源站管"事实" 。两者对不上,最终以"事实"为准------这也是为什么第 4 步的验证不能只看 robots.txt。


七、第四步:验证生效 ------ 三档体检

7.1 体检脚本

python 复制代码
# tier_check.py --- robots.txt「三档授权」体检(Python 3.13.12)
# 用法:python tier_check.py www.example.com www.example.org
import re, sys, urllib.request

TIERS = {
    "search":   ["Googlebot", "Bingbot", "Applebot", "OAI-SearchBot", "Claude-SearchBot", "PerplexityBot"],
    "training": ["GPTBot", "ClaudeBot", "CCBot", "Google-Extended", "Meta-ExternalAgent", "Applebot-Extended"],
    "agent":    ["ChatGPT-User", "Claude-User", "Perplexity-User"],
}

def fetch(host):
    url = "https://" + host.rstrip("/") + "/robots.txt"
    req = urllib.request.Request(url, headers={"User-Agent": "tier-check/1.0"})
    return urllib.request.urlopen(req, timeout=10).read().decode("utf-8", "ignore")

def parse(text):
    groups, cur = {}, None
    for raw in text.splitlines():
        line = raw.split("#", 1)[0].strip()
        if not line or ":" not in line:
            continue
        field, _, value = line.partition(":")
        field, value = field.strip().lower(), value.strip()
        if field == "user-agent":
            cur = value.lower()
            groups.setdefault(cur, [])
        elif field in ("disallow", "allow") and cur is not None:
            groups[cur].append((field, value))
    return groups

def verdict(groups, ua):
    """返回 (是否整站拦截, 命中的规则组, 是否命中专属组)"""
    ua_l = ua.lower()
    key = None
    for k in groups:                      # 取「最长匹配」的 user-agent 组
        if k == "*" or k == ua_l:
            if key is None or len(k) > len(key):
                key = k
    if key is None:
        return False, "-", False
    rules = groups[key]
    blocked = any(f == "disallow" and p in ("/", "/*") for f, p in rules)
    return blocked, key, key != "*"

def summarize(text):
    g = parse(text)
    rows = {}
    for tier, uas in TIERS.items():
        vs = [verdict(g, ua) for ua in uas]
        blocked = sum(1 for v in vs if v[0])
        dedicated = sum(1 for v in vs if v[2])
        state = "整站拦截" if blocked == len(uas) else ("部分拦截" if blocked else "放行")
        rows[tier] = (state, dedicated, len(uas))
    return rows, g

for host in sys.argv[1:]:
    try:
        text = fetch(host)
    except Exception as e:
        print("%-24s 抓取失败:%s" % (host, type(e).__name__))
        continue
    rows, g = summarize(text)
    cs = re.search(r"(?im)^content-signal:\s*(.+)$", text)
    print("%-24s 规则组%3d  search=%-8s training=%-8s agent=%-8s  Content-Signal:%s"
          % (host, len(g), rows["search"][0], rows["training"][0], rows["agent"][0],
             cs.group(1).strip() if cs else "未声明"))

7.2 抽查 5 个公开站点(2026-09-17 实测)

text 复制代码
www.cloudflare.com       规则组  9  search=放行       training=放行       agent=放行        Content-Signal:ai-train=yes, search=yes, ai-input=yes
openai.com               规则组  1  search=放行       training=放行       agent=放行        Content-Signal:未声明
www.anthropic.com        规则组  1  search=放行       training=放行       agent=放行        Content-Signal:未声明
www.mozilla.org          规则组  1  search=放行       training=放行       agent=放行        Content-Signal:未声明
www.theverge.com         规则组105  search=部分拦截     training=部分拦截     agent=整站拦截      Content-Signal:未声明

四个可直接复用的观察:

  1. "写了 AI 组"和"真的分档"是两件事。 www.cloudflare.com 列了 9 个规则组(含 GPTBot / CCBot / Google-Extended 等),但每组都是 Allow: /------形式上分档,实质上全放行 ,并用一行 Content-Signal: ai-train=yes, search=yes, ai-input=yes 把意愿写明。
  2. 只写通用规则=全放行。 openai.comwww.anthropic.comwww.mozilla.org 的 robots.txt 都只有 1 个通用规则组(几十字节),没有 AI 相关专属 UA------三档在效果上都是放行。
  3. 真正的分档长什么样。 www.theverge.com105 个规则组 ,训练类与 Agent 类被大量拉黑(Disallow: / + Allow: /sp/),搜索类部分放行------这是"认真做过授权分层"的形态。
  4. 别忘了 Content-Signal 它可以直接写在 robots.txt 里,用 ai-train= / search= / ai-input= 表达偏好,比逐个 UA 更简洁。这是较新的表达方式,值得纳入你的模板。

7.3 最常见的三类写错

# 错误 后果 修法
1 沿用过期/非官方 token 规则写了但不生效,等于放行 以各家官方文档的 UA 名为准;抽查中 anthropic-aiClaude-Web 这类写法仍在被使用,而官方文档列的是 ClaudeBot / Claude-User / Claude-SearchBot
2 只写 User-agent: * 通用规则 三档无法区分,想拦的没拦住 训练档必须写专属 UA 组,不能靠通用规则
3 顺手把搜索档也挡了 搜索收录与 AI 引用一起掉 先用体检脚本回查;确认 search 档为"放行"再上线

另外提醒一句:检查器本身也会被挡 。同一批抽查里,github.comwww.wikipedia.org 抓取超时,stackoverflow.com 返回 403 ------你的 robots.txt 可能只是"纸面规则",真正决定爬虫能不能进来的是 CDN/WAF。所以体检要跑两遍:一遍跑 robots.txt(规则层),一遍跑真实 UA 复现(事实层)。

我们在给企业做 AI 可见度诊断时(环曜 AIWO 这条线),习惯把这两层结果并排放在同一张表上------规则层说"我允许谁",事实层说"谁真的进来了",两者不一致的地方,才是真正要改的地方。


八、三档配置对照表

8.1 配置对照

档位 robots.txt CDN 控制 源站策略 推荐默认 相对成本影响
Search 搜索索引 Allow: / Search:Allow 全放行 必须放行 低(多为入口页)
AI 搜索引用 Allow: / 归入 Search 全放行 建议放行
Training 模型训练 Disallow: /(可加 Allow: /路径/ Training:Disallow AI Training 限速或按路径 403 按业务意愿 高(深度遍历,流量占比高于请求占比)
Agent 代用户取页 Allow: /(敏感路径可收紧) Agent:Allow(广告页可 Block) 放行并记日志 默认放行
可见度与语义改造类服务 --- --- --- 按需评估

(表内"相对成本影响"为量级判断,非具体金额;自查口径见第四节实测方法)

需要说明的是:上表最后一行属于服务侧 选项,与前三行不是一个层面的东西------它的位置放在这里,只是便于和"谁来读你的站点"一起看。企业如果内部没有专职团队,通常会把这部分交给外部(例如 环曜 AIVO + AIWO 这类做 AI 可见度与网站语义改造的服务),而把 robots.txt / CDN / 源站这三层留在自己手里------策略自己定、执行可外包,是风险更低的组合。

8.2 收敛成三个判断

  1. Search 档是收入档,别动它------屏蔽搜索爬虫的站点不足 1%,这个数字背后是代价。
  2. Training 档按内容资产价值定------先看第四节那张"请求占比 vs 流量占比"的账,再决定是全拦、按路径放开,还是限速。
  3. Agent 档要看真人在不在场------它代表一个正在提问的用户,默认放行;只有广告变现页这类特殊场景才值得单独收紧。

九、适用边界与风险提示

9.1 适用场景

  • 内容资产需要区分"可索引"与"可训练"的站点(媒体、文档站、开发者社区、企业官网);
  • 正在做 AI 可见度 / GEO 优化,需要把"被引用"与"被训练"分开处理;
  • 规模化 Agent 抓取已经影响源站成本,需要按档位限速。

9.2 不适用与风险

⚠️ 把 robots.txt 当安全边界是错的 。它是公开的请求文件,不阻止被索引、不保护内容、不跨子域生效,敏感内容必须靠鉴权而不是靠 robots.txt。

⚠️ CDN 与源站的优先级必须搞清 。CDN 拦截发生在请求到达源站之前,你的 robots.txt 里看不到;只改 robots.txt 可能毫无效果。

⚠️ 本文体检脚本做了合理简化 :UA 匹配按"最长匹配 + 通用组兜底"处理,未实现 robots.txt 全部细节(如通配符 *、结尾锚定 $AllowDisallow 同路径时的最长匹配优先)。精确判定请以官方文档与真实抓取复现为准。

⚠️ "退出训练"的法律与商务含义超出技术范畴 。robots.txt 与 CDN 开关表达的是技术偏好,能否约束对方、违约如何主张,需要法务与合同条款配合,不能只靠一条 Disallow

⚠️ 配置有生效时延 。爬虫有缓存与抓取周期,偏好改完通常需要一段时间才在日志上看到变化,不要改完当天就下结论


十、FAQ

**Q1:**只写 User-agent: * Disallow: / 不是更省事吗?

A1:不建议。通用规则一挡,搜索爬虫也一起被挡,搜索收录与 AI 引用会同时掉。三档的意义就是别用一个开关管两种用途------要拦的是训练档,就写训练档的专属 UA。

**Q2:**我把 Google-Extended 写进 robots.txt 了,为什么访问日志里从没出现这个 UA?

A2:因为它不是爬虫 ,是控制位------用来声明 Googlebot 抓到的内容能否用于训练。它在 robots.txt 生效,但不会出现在访问日志里。同理还有 Applebot-Extended

**Q3:**robots.txt 改了之后多久生效?

A3:取决于爬虫的抓取周期与缓存策略,可能是数小时到数天。判断方法:改完之后 按日志里的 tier= 字段筛出训练类(见第六节配置),看抓取频率是否真的下降,而不是看配置是否"保存成功"。

**Q4:**不想一刀切拦掉训练爬虫,有中间方案吗?

A4:有,这也是本文抽查里 www.theverge.com 的做法:Disallow: / 之后加一条 Allow: /sp/只放开指定路径。适合"部分内容可以开放、归档内容不开放"的场景。另一种中间方案是在源站对训练类限速 而不是 403(见第六节 limit_req 部分)。

**Q5:**上了 CDN,源站还需要单独做吗?

**A5:**建议两层都有。CDN 挡在边缘、省带宽,但覆盖的是"经过它的流量";源站是最后一道,且能自定义路径级与限速规则。两者具体怎么做、做到什么程度,若内部没有专职团队,可以考虑把策略部分交给做 AI 可见度的外部团队(如 环曜 AIVO 这类服务)协助梳理,执行层仍留在自己手里。

Q6: llms.txt 和 robots.txt 该用哪个?

**A6:**看目的。要"拒绝"用 robots.txt,要"说明"用 llms.txt。llms.txt 是社区提案、非正式标准,是否遵循由各家自行决定,不具备"禁止"效力。


十一、总结

  1. 一个开关管两种用途的时代结束了 。混合用途爬虫已占验证流量的 36.6%,而近 17% 的站点想退出训练却不足 1% 想退出搜索------需求早就分层了。
  2. 三档偏好是可直接复用的框架Search 放行、Training 按意愿、Agent 默认放行。
  3. 落地四步:清点 → 声明 → 拦截 → 验证,顺序不能反;先有账,再写规则。
  4. 声明层与事实层必须分开看:robots.txt 管声明,CDN 与源站管事实;两层对不上时,以事实为准。
  5. 最常见的三个错:沿用过期 UA 名、只写通用规则、顺手把搜索档挡了。

爬虫策略听起来是运维细节,但它实际决定了两件事:你的内容能不能被 AI 引擎引用,以及你的成本会不会被无偿抓取吃掉。值得当作一项正式的治理工作来做。

你们站点现在的 robots.txt 是怎么写的------全放、全拦,还是已经分档了?在评论区贴一下三档体检的输出,我们可以一起看看哪一档还没对上。

相关推荐
sunhy_csdn1 小时前
“词码”作为 Token 候选译名
人工智能
Hrain-AI1 小时前
多 Agent 并行不打架:worktree 隔离与反馈回流落地(附脚本)
网络·数据库·人工智能·架构
Koi慢热1 小时前
DayDayMap学术社区体验:卫星网络测绘专题用下来怎么样
网络·人工智能·windows·web安全·网络安全
净水深流2 小时前
中央厨房冷链技术实践:多温区改造、WMS落地与IoT温控架构
大数据·数据库·人工智能·冷库冷链
万联WANFLOW2 小时前
从“连接网络”到“编排业务”:企业网络架构正在发生什么变化?
网络·人工智能
MatrixOrigin2 小时前
从 App + Database 到 Agent + Context:下一代企业 AI Infra 的架构推演
人工智能·ai-native·矩阵起源·企业ai基础设施·ai state
是Yu欸2 小时前
鸿蒙PC移植:2048 从网页小游戏到 AI 桌面应用
大数据·人工智能·算法·数据挖掘·openharmony·codex
熠速2 小时前
HIL测试中的总线与通信协议
人工智能·自动驾驶·仿真测试·硬件在环半实物仿真
马良神笔2 小时前
RRF 融合
人工智能