跳到正文

AI 爬虫访问审计

速览要点

难度
进阶
预计耗时
首次完整走一遍约半天,之后复检约 1 小时
前置条件
AI 爬虫、robots.txt
它核实什么
你决定放行的爬虫,是不是真的抓得到你的页面;你决定屏蔽的,是不是真的停下来了。靠证据,不是靠把自己的 robots.txt 再读一遍
方法
把意图、声明、实际、观测四种状态对齐。每一条发现,都出在相邻两种状态对不上的地方
代价最高的一处
声明与实际对不上。CDN、WAF 或机器人管理的默认设置,可以把 robots.txt 里明确放行的爬虫挡在门外,而从那份文件里根本看不出来
方法的硬性边界
伪造用户代理字符串的探测只能证明放行,永远证明不了屏蔽。你假冒的 GPTBot 收到 403,最可能的解释是防伪造机制正常在工作
按什么判定
基准是你写下的策略,不是开放程度越高越好。按计划屏蔽训练爬虫不算发现;策略根本没写下来,那才算

1. 这次审计要回答什么

一次 AI 爬虫访问审计,核实的是两件事:你决定放行的爬虫,是不是真的抓得到你的页面;你决定屏蔽的,是不是真的停下来了。两边都需要证据。把自己的 robots.txt 再读一遍,哪一边都证明不了。

原因在于,robots.txt 是一份声明,不代表实际交付了什么。一个站点完全可以在文件里明确放行某个检索爬虫,实际请求却被 CDN 的机器人管理默认设置、WAF 托管规则、地域封锁或限速拦在网络层。文件里不会留下任何痕迹。这类失效之所以代价最高,正是因为所有人第一时间都去查那份文件,而这件事恰恰在文件里看不出来。

另一个方向同样需要证据。写了 Disallow 不等于对方停了:RFC 9309 写明其规则「并不构成一种访问授权」,遵守与否是厂商公布的政策,不是技术上的保证。到底谁真的来过,只有日志能回答,而且要先把身份确认下来。

所以这次审计的产出是一份对不上的清单:每条发现都指明是哪两种状态互相矛盾、证据是什么、严重到什么程度,以及该由哪一层去修(内容层、配置层,还是网络层)。下面用意图、声明、实际、观测这四种状态来拆解访问,这是 GEO Wiki 为做这种比对而定的组织方式,不是行业通行的审计口径;它之所以立得住,是因为真正能落到行动上的从来不是这四种状态本身,而是它们之间对不上的地方。

2. 开始审计前:范围、程序清单、意图策略、证据窗口

有四件事要先定下来,它们决定后面每一条发现到底意味着什么

要决定的事可选项怎么判断
范围每个主机 × 每种协议 × 每个 CDN 区域robots.txt 是按主机生效的:主域、wwwdocs.blog. 各自都需要一份。漏审子域是最常见的覆盖缺口
程序清单类别选,不按名气选训练、检索、用户触发这三类各至少取一个代表,再加上你真正有受众的那些引擎。分类依据见 AI 爬虫
意图策略写下来了,还是没有没有它就根本产生不了发现,这份缺失本身就是第一条发现(见 §8)
证据窗口日志保留期与分析数据保留期保留期短于爬虫的回访周期,观测层的每一个结论都不成立。开审之前先确认

意图策略这一行的分量比它的篇幅要重。报告里的每一条发现,衡量的都是它与意图之间的偏离,而不是开放程度够不够高。一个有意拒绝训练爬虫的站点,GPTBot 被 Disallow 不构成发现,那正是策略在按预期生效;同一份策略下检索爬虫被 WAF 挡掉才是发现,因为没有人做过这个选择。

什么时候该跑一次:CDN 或 WAF 有变更之后、站点迁移之后、新加了一层防护之后、更换 CMS 或插件之后、有新的爬虫上线时,以及厂商默认策略的变更日(§7 里就有一处带日期的变更)。

3. 访问的四种状态

四种状态,各有各的证据来源。

状态它回答什么证据来源
意图(intended)你按类别决定了什么?一份写下来的策略(没有则构成第一条发现)
声明(declared)站点在每个主机、每种协议下对外声明了什么?实地取回 /robots.txtX-Robots-Tag、robots meta
实际(effective)一个真实请求实际拿到了什么?合成探测:状态码、响应体积、正文哈希
观测(observed)谁真的来过,身份是否站得住?访问日志或边缘日志,加上 IP 段比对与反向解析

单看任何一种状态都没有意义。真正能落到行动上的发现,来自相邻两种状态之间的落差,而这样的落差只有三类:

对不上的地方常见根因该由哪一层修
意图 ≠ 声明CDN 在边缘注入的 robots.txt 覆盖了你的;CMS 或插件的默认值;测试环境配置被带上线;子域没有自己的文件配置层
声明 ≠ 实际机器人管理、WAF 托管规则、地域或 ASN 封锁、限速、人机校验拦截页网络层,最常被漏掉的一类
实际 ≠ 观测没人来(问题出在有没有被发现、优先级排得高不高,不是屏蔽);或者写了 Disallow 对方照样来(不遵守,或冒用身份)分发层或安全层

按声明、实际、观测的顺序做,因为后一步都比前一步贵;很多时候还没走到更贵的那一步,便宜的证据就足以定位问题。

4. 第一步:核查声明层

把文件实际取回来,而不是在浏览器里看一眼;范围内的每个主机都要取:

for h in example.com www.example.com docs.example.com blog.example.com; do
  printf '%-24s ' "$h"
  curl -sS -o "robots-$h.txt" -w '%{http_code} %{size_download}B\n' "https://$h/robots.txt"
done
shasum robots-*.txt

这一步能得出两个判断。4xx 意味着这个主机根本没有声明任何规则,遵守协议的爬虫此时可以抓取任意路径。哈希一致,说明确实是同一份策略在全站生效;哈希不一致,说明你有一批按主机区分的策略,而这应该是有人特意决定的结果。分组合并、路径优先级这些解析规则,遵循 robots.txt 里的通用说明。

检查边缘是否做了覆盖。CDN 可以在边缘注入或替换 robots.txt,也就是说,你对外提供的文件和仓库里的文件可能并不一样,而两边都没有人改动过。判断方法是比对内容:把边缘取回的文件和仓库里的文件逐字节对上。这比看任何一个配置面板都可靠,因为它量的是最终产物,而不是产物背后的意图。

页面级指令也属于这一层X-Robots-Tag 响应头和 robots meta 标签同样是对外声明,但它们管的是索引和展示,不是抓取:

curl -sSI "https://example.com/pricing" | grep -i 'x-robots-tag'

这个区别在后面归并时很关键。Google 的文档写明,如果一个页面在 robots.txt 里被屏蔽,「Googlebot 将永远不会抓取该页面,也就永远读不到页面上的任何 meta 标签」(见 robots meta 标签规范)。抓取屏蔽和索引屏蔽表现出来的症状不同,修法也不同,在这里就记清楚是哪一种,能省掉 §8 里的一次误判。

关于 llms.txt 需要说明一句:它既不授予访问权限,也不拒绝任何访问,因此在这次审计里不会产生任何发现。它是否存在、内容是否准确,见 llms.txt 部署

5. 第二步:探测实际层

对同一个网址发两次请求,一次作基线,一次冒充爬虫,比较三项,而不是只比一项:

URL="https://example.com/pricing"
UA_BROWSER="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
UA_BOT="PerplexityBot"   # 多数 UA 规则只匹配这个名字本身,够用了

curl -sS -A "$UA_BROWSER" -o base.html -w 'baseline %{http_code} %{size_download}B\n' "$URL"
curl -sS -A "$UA_BOT"     -o bot.html  -w 'bot      %{http_code} %{size_download}B\n' "$URL"
shasum base.html bot.html

只看状态码不够,所以命令里加上了体积和哈希:人机校验页和软屏蔽都会返回 200。各家公布的完整用户代理字符串带有会变动的版本号,逐个爬虫的记录见 GPTBotClaudeBotPerplexityBot

不要只测一个网址,按一个矩阵跑:首页、一个核心内容模板、一个带分页或筛选的路径、一个受限路径。每一格都记满五列:网址模板、爬虫令牌、状态码、体积、判定。

信号你看到的是什么
403401硬屏蔽
429,或持续请求一段时间后开始失败限速
200,但响应体积远小于基线人机校验或拦截页
换一个出口地区结果就不同地域或 ASN 封锁
200,体积也合理,但初始 HTML 里没有正文抓到了空壳,见下

抓到了空壳是这次审计唯一一类只负责发现、不负责修复的问题。页面返回 200,正文却因为依赖客户端渲染而不在响应里,按完整 GEO 审计的分层这属于第 2 层,修法见面向 AI 爬虫的 SSR。在这一步顺手就能发现它,因为正文体积比对本来就要做。

必须讲清楚的方法边界:伪造用户代理字符串的探测只能证明放行,证明不了屏蔽。厂商爬虫通常按公布的 IP 段或反向解析放行,而不是按用户代理字符串放行。Cloudflare 的已核验程序机制就是一例:它要求程序通过 Web Bot Auth 密码学签名、公布 IP 清单或反向解析三者之一证明自己的真实身份,同时行为上不得滥用(见 Verified bots)。所以你假冒的 GPTBot 收到 403,最可能的解释是防伪造机制正常在工作,而不是真爬虫被挡住了。这个推断只在一个方向上成立:假令牌拿到 200,真令牌基本也过得去。要确认屏蔽,只能靠 §6。

6. 第三步:核实观测层

并不是每个人都拿得到源站访问日志;直接假定大家都有,等于把最需要这一步的人挡在门外。

日志来源能回答什么怎么读
源站访问日志(nginx、Apache)四个问题都能回答:谁来的、什么时候来、拿到什么状态码、抓了哪些网址直接 grep
CDN 分析或日志导出边缘侧的真实情况,包括那些还没到源站就被拦下的请求平台分析面板或日志导出
不提供访问日志的托管平台有限,只能看平台自带的机器人分析能给出多少源站日志和边缘数据都没有的话,这个缺口本身就是一条发现,先把可观测性补上

这里有一个硬限制:源站日志看不到被 CDN 在边缘拦下的请求。§3 里声明与实际对不上的那一类,恰恰只在边缘侧的数据里留下痕迹,这也正是它在只查源站日志的站点上长期无人察觉的原因。

保留期是另一处容易出问题的地方,而且往往比大家以为的短得多。Vercel 的文档写明,运行时日志在 Hobby 套餐保留 1 小时、Pro 保留 1 天(开通 Observability Plus 后为 30 天),静态请求只有在命中缓存时才会进入运行时日志,要拿到完整的静态请求日志需要开启日志导出(见 Vercel 运行时日志)。一个按月回访的爬虫,在一天的窗口里根本看不见。

按令牌汇总到访情况:

# 哪些 AI 令牌来过,来自哪些 IP,拿到了什么?
# 按自己的日志格式调整 awk 的列号($1 为客户端 IP,$9 为状态码)。
grep -iE 'GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|Claude-SearchBot|Claude-User|PerplexityBot|Perplexity-User|Googlebot|Bingbot' access.log \
  | awk '{print $1, $9}' | sort | uniq -c | sort -rn | head -40

这里要看的是每个令牌的状态码分布,不是它一共来了多少次。一个令牌持续来访、拿到的却是一片 403,那是确认无疑的屏蔽;拿到 200 则是确认放行,前提是身份站得住。

确认身份要走两步,不是一步。先把来源 IP 和厂商公布的清单比对,再做前向确认反向解析(forward-confirmed reverse DNS)。Google 的文档把这个顺序写得很直接:先对来访 IP 做反向解析,再把得到的主机名正向解析回去,确认能解回同一个地址(见 Verify Google requests)。

host 203.0.113.10          # → 反向解析得到主机名
host crawl-203-0-113-10.googlebot.com   # → 必须解回 203.0.113.10

各家公布的清单地址,核对时间为 2026 年 7 月 29 日:

厂商令牌公布的 IP 清单说明
OpenAIGPTBot、OAI-SearchBot、ChatGPT-Usergptbot.jsonsearchbot.jsonchatgpt-user.json逐程序分开的文件;GPTBot 与 OAI-SearchBot 之间有共用网段
AnthropicClaudeBot、Claude-SearchBot、Claude-Userclaude.com/crawling/bots.json合并成一份文件;Anthropic 写明,来源 IP 只要出现在这份清单上,「即表明该爬虫来自 Anthropic」
PerplexityPerplexityBot、Perplexity-Userperplexitybot.jsonperplexity-user.json文档建议用户代理字符串匹配与 IP 核验两者并用
GoogleGooglebot、Google-Extendedcommon-crawlers.json,另有特例爬虫和用户触发取页各一份这些文件已于 2026 年 3 月迁至 /crawling/ipranges/;反向解析结果落在 googlebot.comgoogle.com 的主机名上
MicrosoftBingbot未公布只能靠反向解析到 search.msn.com 下的主机名,或使用 Verify Bingbot 工具

有两个结构性事实会改变这张表的读法。Google-Extended 是一个背后没有爬虫的控制令牌,因此它根本不会产生任何日志行,观测层对它天然给不出证据,只能在声明层核对。另外,公布的 IP 清单是用来确认入站请求身份的,不是一份长期有效的屏蔽名单。Anthropic 说得很直接:「屏蔽 Anthropic 程序所使用的 IP 地址这类替代做法,可能无法正确生效,也不能持续保证退出」,因为它的爬虫跑在公有云地址上(见 Anthropic 爬虫文档)。

日志里没有,该怎么读。没有记录不等于被屏蔽。可能是它还没发现这些页面,可能优先级排得很低,可能回访周期长过你的保留期,也可能它对你这类页面根本不用自己的爬虫。要和 §5 的结果对着读:实际层干净、观测层空白,说明问题出在有没有被发现、抓取优先级排得高不高,要靠更强的更新通知和收录覆盖信号去解决,做法见 Sitemap 与 IndexNow,跟能不能访问无关。

有一类爬虫不适用这套方法。用户触发的取页发生在有人问到某个具体网址的时候,量小且不规则,想靠到访次数去验证策略,在哪个方向上都立不住。robots.txt 究竟约不约束它们,官方文档另有说明,见 ChatGPT-User

7. 基础设施层如何越过你的设置

真正决定结果的那部分,越来越不在你自己的文件里。

越过设置的因素它改变的是哪一段为什么容易被漏掉
CDN 机器人管理的默认设置声明 → 实际按套餐档位生效,不看你怎么配
边缘注入的 robots.txt意图 → 声明仓库里那份文件不再是对外提供的那份
WAF 托管规则集声明 → 实际按厂商的节奏更新,不按你的
按次计费与协商类控制声明 → 实际可能返回 402 Payment Required,看上去并不像一次屏蔽
平台级默认策略变更声明 → 实际到某个日期自动生效,你一行配置都不用改

识别能力随套餐档位而不同,这直接决定你那套控制实际拦得住什么。Cloudflare 写明「在免费套餐下,AI Crawl Control 依据用户代理字符串识别 AI 爬虫」,更彻底的机器人管理识别需要付费套餐,屏蔽时可以返回 403402(见 Manage AI crawlers)。按用户代理字符串识别和按身份识别,失效的方式完全不同,知道自己用的是哪一种,会改变你在 §5 里对一个 403 的读法。

有一处带日期的变更值得提前安排。Cloudflare 说明,从 2026 年 9 月 15 日起,「在展示广告的页面上,训练类和 agent 类将默认屏蔽,搜索类仍然默认放行」,这套默认值作用于新接入的域名,已有客户可以提前设定自己的偏好(见 Cloudflare)。这件事本身好坏另说,对审计的影响是结构性的:你名下的任何一份文件都没有改动,实际访问结果却变了。

在证据允许的范围内只能说到这里:控制权正在从一份文本文件,转移到网络层和合同上。更远一步是用密码学来验证程序身份:IETF 已经成立了 Web Bot Auth 工作组,draft-meunier-web-bot-auth-architecture 提出让自动化客户端「对发出的请求做密码学签名,使 HTTP 服务器能够可靠地核验其身份」。这份草案目前是个人提交、被列为工作组可能采纳的输入文档之一,还不是标准,所以它指出的是方向,今天还不能当作一项可以审计的控制手段。对审计的实际影响是:声明层的证据价值在下降,实际层和观测层的在上升。

8. 归并:给发现分类并排序

每条发现都写成三部分:是哪两种状态对不上、证据是什么、该由哪一层修。严重级别沿用完整 GEO 审计的那套分级,但判定依据是受影响的爬虫类别,不是层号。

发现严重级别判定依据
检索爬虫在网络层被挡,与意图相反阻断级立刻失去被引用的资格,而且在文件里看不出来
检索爬虫在 robots.txt 里被 Disallow,与意图相反阻断级代价相同,但修起来最便宜
没有写下来的意图策略阻断级其余每一条发现都无从判定
子域或协议没有自己的 robots.txt,行为与主域不一致重大级没人会注意到的覆盖缺口
返回 200,正文却是空壳重大级(转第 2 层处理)抓得到,读不到
限速导致抓取深度被截断重大级覆盖会缺掉一部分
训练爬虫按计划被屏蔽不算发现策略正在按预期生效
到访记录与声明的策略相矛盾次要到重大级,看量级要修的地方在网络层,不在文件层

严重级别不等于优先级。给 WAF 加一条白名单,和把整站从客户端渲染架构迁走,不是一个量级的工作量,所以在把清单变成行动计划之前,先按影响大小、把握有多大、改起来有多难重新排一遍;完整 GEO 审计对全部六层用的也是同一套排序方法。

9. 结论可靠性与常见陷阱

  • 只在自己的网络里做探测。办公室 IP 常常本来就在白名单里,结论无法推广到公网。
  • 假用户代理字符串收到 403,就当成屏蔽的证据。这一条的误读代价最高,见 §5。
  • 只比状态码。人机校验页和空壳 200 会被整个漏掉。
  • 只查源站日志。被边缘拦下的请求根本到不了源站,而那正是要找的那一类。
  • 只审主域robots.txt 按主机生效,每个子域都要单独查。
  • 日志保留期短于回访周期。观测层因此支撑不起任何结论。
  • 只抽一个网址模板。按路径生效的规则,以及不同模板之间的差异,都会被平均掉。
  • 刚改完 robots.txt 就去复检。生效不是即时的,各家公布的时长不同,而且往往只覆盖搜索那一侧:OpenAI 公布的数字就只针对搜索结果,见 GPTBot
  • 把没有被引用当成访问问题。那是另一件事,要量它得用引用追踪
  • 只审一次。厂商默认设置和托管规则集会在你没有参与的情况下改变结果(见 §7)。

10. 报告交付物与复检节奏

每次都要交付的内容:

  • 报告头:审计日期、范围内的主机清单、程序清单、本次对照的意图策略版本,以及证据窗口。
  • 四种状态的取证记录:逐主机记录每种状态是什么,附上命令输出或日志片段。
  • 对不上的清单:每条写明是哪两种状态矛盾,附严重级别和该修的那一层。
  • 排好序的修复项:§8 里重排之后的那份清单。
  • 与上次的差异:这次和上次比变了什么,以及变化是因为你动了手,还是因为厂商动了手。

复检节奏按成本拆开。声明层和实际层足够便宜,适合排进定期任务;厂商默认设置一旦变更、托管规则集一旦更新,靠的就是这一层去接住。观测层跟着完整审计走:按季度,或按 §2 里的触发条件。

然后把复核日期写进策略本身,和那些指令写在一起。外部的限制本身一直在变:一项覆盖 14000 个域名的纵向研究发现,仅 2023 到 2024 一年之间,C4 语料中就有超过 5% 的 token 被完全设限,而在其中维护最活跃的那部分来源里,这个比例超过 28%(见 Longpre 等,2024)。一份定了之后再没回看过的策略,面对的是一个已经变过的局面。

11. 相关条目

参考资料

Primary

Secondary

常见问题

为什么读一遍自己的 robots.txt 还不够?
因为 robots.txt 是一份声明,不代表实际交付了什么。你的文件可以明确放行某个检索爬虫,同时 CDN 的机器人管理默认设置、WAF 的托管规则、地域封锁或限速在网络层把它挡住,而这些在文件里一处都看不到。反过来同样成立:写了 Disallow 不等于对方停了,因为遵守是厂商声明的政策,不是技术上的保证。真正发生了什么,只有探测和日志能回答。
我直接用 GPTBot 当用户代理字符串 curl 一下自己的站点,能测出有没有被屏蔽吗?
只能测出一个方向。假冒的 GPTBot 拿到 200,真爬虫基本也拿得到。但如果拿到 403,最可能的解释是防伪造机制正常在工作:厂商爬虫通常按公布的 IP 段或反向解析放行,而不是按用户代理字符串放行,所以一个假的字符串会被当成冒用者处理。要确认屏蔽,只能看日志,而且身份要先核实过。
如果我的托管平台不提供访问日志怎么办?
那么可观测性本身就是第一条发现,而不是跳过这一步的理由。不少无服务器(serverless)平台只提供函数级日志,保留期还很短:Vercel 的文档写明 Hobby 套餐保留 1 小时、Pro 保留 1 天,静态请求只有命中缓存时才会进运行时日志,要拿到完整的静态请求日志得开日志导出。边缘日志或 CDN 分析可以替代源站日志;两者都没有,就先把这个缺口补上,再去判断哪些爬虫到过。
某个爬虫在日志里一次都没出现,是被屏蔽了吗?
不一定,没有记录并不构成屏蔽的证据。它可能还没发现你的页面,可能把优先级排得很低,可能回访周期比你的日志保留期还长,也可能对你这类页面根本不用自己的爬虫。要和探测结果对着读:实际层返回干净的 200、观测层却是空的,那说明问题出在它有没有发现你、抓取优先级排得高不高,而不是能不能访问。
按 IP 屏蔽爬虫管用吗?
作为强制手段并不可靠,厂商自己也这么说。Anthropic 写明「屏蔽 Anthropic 程序所使用的 IP 地址这类替代做法,可能无法正确生效,也不能持续保证退出」,因为它的爬虫跑在公有云地址上。公布的 IP 清单是用来确认入站请求身份的,本次审计正是这样用它;它不适合当成一份长期有效的屏蔽名单。

相关指南与百科

参考来源

一手来源

  1. RFC 9309: Robots Exclusion Protocol · IETF · 2022-09-01
  2. Verify requests from Google crawlers and fetchers · Google Search Central
  3. Google crawler IP ranges — common-crawlers.json · Google
  4. New location for the Google crawlers' IP range files · Google Search Central
  5. Robots meta tag, data-nosnippet, and X-Robots-Tag specifications · Google Search Central
  6. Does Anthropic crawl data from the web, and how can site owners block the crawler? · Anthropic
  7. Anthropic crawler IP list (bots.json) · Anthropic
  8. Perplexity Crawlers (PerplexityBot / Perplexity-User) · Perplexity AI
  9. Overview of OpenAI Crawlers · OpenAI
  10. How to verify Bingbot · Microsoft Bing
  11. Verify Bingbot tool · Microsoft Bing
  12. Verified bots · Cloudflare
  13. Manage AI crawlers — AI Crawl Control · Cloudflare
  14. Your site, your rules: new AI traffic options for all customers · Cloudflare · 2026-07-01
  15. Runtime Logs — retention limits by plan · Vercel
  16. HTTP Message Signatures for automated traffic: Architecture (draft-meunier-web-bot-auth-architecture) · IETF (Internet-Draft) · 2026-03-02

二手来源

  1. Consent in Crisis: The Rapid Decline of the AI Data Commons · Longpre et al. (arXiv / NeurIPS D&B)
  2. Anthropic clarifies how Claude bots crawl sites and how to block them · Search Engine Land
  3. Perplexity is using stealth, undeclared crawlers to evade website no-crawl directives · Cloudflare
最近更新: 2026-07-29 作者: Ray Yang 主题: 实践