SEO时代有一件事是确定的:Googlebot来没来、抓了哪页、收录没有,Search Console会给你答案。AI时代这件事归零了——ChatGPT、Claude、豆包的一次回答可能正在引用你的内容,但它们的爬虫来没来、读了哪几页、漏了哪几页,没有任何平台给你这个视图。你的内容在AI眼里存不存在,比你的站有没有漏洞更难看清:后者至少人人知道去跑个扫描器,前者连"该去哪里看"都没有。
这个品类有个名字,GEO(Generative Engine Optimization,生成式引擎优化)。卖概念的多,拿数据说话的少。我挑了GitHub上328星的开源项目GEOInflow,在本地把整套系统跑起来,往它的日志管道里投了一批精心设计的料:27个爬虫身份61次请求、三组官方IP对照、3个未知UA、3次纯浏览器访问、一份20页的内容清单、14条AI平台引荐。它接住了多少、漏了什么、报得多诚实,下面是全部数据——包括一个它自己的漏报。
它是什么:把你日志里属于AI的部分翻译成人话
GEOInflow的底座是Umami v3.4.1,一个老牌开源网站统计系统。它不去爬任何人的站,而是在统计底座上加了一层AI视角,做三件事:
识别。内置60条HTTP爬虫身份规则,GPTBot、ClaudeBot、PerplexityBot、Bytespider、Kimi系、豆包的HySpider都在名单上,加robots用途和签名agent两条辅助规则,目录共64条身份。
核验。内置24个官方IP范围来源(crawler-range-baselines.json,含OpenAI、Anthropic、Kimi、Meta等)。UA声称自己是GPTBot,来源IP却不在OpenAI官方网段,它会记账。
归因。用户从chatgpt.com点进来,这条引荐被单独归为AI引荐——ai-platform-coverage.json规则表数千行,ChatGPT、Claude、Perplexity、Gemini、Copilot加豆包、Kimi、DeepSeek、文心一言都在表里。
部署走docker compose,自构建镜像1.77GB。过程不算顺:构建三次死在同一位置——Docker VM的7.2GB内存被我另一批实验容器(14个,占3~4GB)挤占,Next.js编译OOM带崩buildkit;腾出内存后第四次构建589.6秒通过。DB-IP城市库的构建期下载挂过6分钟,预下载mmdb文件兜底解决。.env漏配POSTGRES_USER会让应用启动循环报P2010。坑都记在文末,先看实验。
主实验:六组对照,往日志里投料
合成Nginx combined日志67行(固定种子可复现),六组料一次投完:
| 组 | 投放 | 要测什么 |
|---|---|---|
| A识别 | 27个UA:20个AI爬虫 + 4个传统搜索 + 3个训练/营销爬虫,共61次请求 | 识别是否全对,有无冒认漏报 |
| B核验 | 官方UA × 官方IP / 伪装IP(8.8.8.8、1.1.1.1、9.9.9.9) | 伪装的GPTBot能否被拆穿 |
| C未知 | GPTB0t(O换成数字0)、FakeGPTBot、TotallyUnknownBot | 会不会臆造身份 |
| D分账 | Chrome浏览器3次访问 | 人类流量会不会混进爬虫口径 |
| 盲区 | 20页内容清单,设计12页被爬 | 没被爬的页能否如实上报 |
| E引荐 | 14条referrer:10个AI平台 + 2个传统搜索 + 2个无法归因 | 归因是否无损 |
日志里还埋了异常行为:一个404、一个500、一次HEAD、一个301,以及PerplexityBot对同一热门页连抓6次。
数据展开:四个数字
其一,26/27——识别近乎全对,但漏了一个国产爬虫。bots统计返回26个身份、59次请求,每一笔都对得上账:GPTBot 5次(3次成功 + 1次404单独计入status4xx + 1次伪装IP),ClaudeBot 5次(含1次500单列),PerplexityBot 8次——对热门页的6次重复抓取完整暴露;OAI-SearchBot的HEAD请求单列head字段,Bytespider的301也进了status3xx。字段的切分方式说明它不是在数UA,是在读行为。
差的那一笔很刺眼:KimiBot(Moonshot的训练爬虫)的2次请求完全没进任何身份的统计。规则目录里明明在册(recognition接口的启用名单含kimibot),实际UA却没被匹配到,也没被冒认给同家的Kimi-SearchBot——从爬虫口径里直接消失。0冒认是真的,1个漏报也是真的,漏的恰好是国产身份。
其二,24次核验、23次报警——核验逐请求自动跑,触发却看IP情报的脸色。我给GPTBot配了个8.8.8.8的来源IP,系统产出一条finding:Declared UA has an official range mismatch(声称身份与官方网段不符),证据rangeMismatches: 1。拉全量数据看,核验比预期勤奋:GPTBot全部5次请求都跑了核验——4次mismatch(3次随机合成IP + 1次8.8.8.8),官方IP(132.196.86.10,取自openai.com/gptbot.json)那次验证通过,计verifiedRange。全部12个被核验的身份共24次请求,23次报警、1次官方段验证通过,无一起漏判。
反例同样重要:ClaudeBot的官方IP(216.73.216.10,取自claude.com/crawling/bots.json)5次请求一次都没触发核验,全部unverified;PerplexityBot的伪装IP(9.9.9.9)同样没被核验。核验是否触发,取决于IP情报库是否覆盖该网段——OpenAI的网段能验,Anthropic的这次没验成。它的核验方向是报警,不是发证:不一致时告警,验证通过也别当成"这就是官方"的证书。
其三,9个盲区——20页目录,45%的内容没有任何AI爬虫碰过。这是全文最重要的数字。设计上20页里12页会被爬,实测爬取去重13条路径——目录内11条,目录外2条(一个不存在的 /blog/typo-page,是爬虫在做404探测;一个 /home,吃了个301)。没被任何爬虫碰过的9页,工具如实报出:/blog/ai-search-trends、/blog/case-study-2、/products/geo-weight、/about、/contact、/whitepaper.pdf、/blog/old-post-2019、/docs/changelog、/pricing/enterprise。名单里有个细节:ai-search-trends在设计上应该被爬,是我生成物料时漏投了——真实盲区比设计盲区多1个,工具照实报,没有讨好设计。
其四,14/14——10家AI平台的引荐数据层全落库。14条引荐事件全部写进website_event表,referrer_domain无损。10个AI域名在规则表全部命中,子域匹配做对了:gemini.google.com归Gemini、copilot.microsoft.com归Copilot、yiyan.baidu.com归文心一言、chat.deepseek.com归DeepSeek。两个故意投的无法归因域名(t.co、example.org)正确落在规则外。国产四家与海外六家同权重,规则表还枚举了81个平台,iflytek、metaso、minimax、baichuan这类长尾国产都在。
展示层要单独说:platforms接口当日81个平台全部显示unknown/unsupported,访问量字段是空的——analytics流水线显示eligibleEvents=14(14条事件已识别为合格事件)而qualifiedPV=0(质量分母没算完)。工具没有吐一个假数字出来,把"未就绪"如实摆在你面前。这算缺点还是优点,取决于你被假仪表盘伤害过没有。
还有两组一句话带过:3个未知UA——包括只差一字符的GPTB0t和名字带GPT的FakeGPTBot——没有出现在任何身份统计里,也没被归到GPTBot名下;Chrome的3次访问没有混进爬虫口径。已知与未知分账,爬虫与人类分账,账本是干净的。
方法局限
四条必须交代。第一,合成日志验证的是"工具能不能读对日志",真实互联网的爬虫分布它回答不了;9/20这个比例不能外推到你的站,真实盲区率要拿你自己的日志跑。第二,单机单站,没有多站点和高并发数据。第三,首次采集的快照早于部分合成日志的时间戳,尾部数据不在首版统计里,我重采修正后才得出本文全部数字——细节写在数据核验说明,给同样要做日志重放实验的人提个醒。第四,这是一个年轻fork的代价:默认管理员密码是liekan而非Umami的umami(测试文件第51行坐实,且它故意拒绝upstream密码),部署后必须改;展示层流水线有未就绪的模块。328星的项目,能力是真的,毛边也是真的。
从数据到行动:内容方的三件事
第一件,显式决定AI爬虫策略。robots.txt里对GPTBot、ClaudeBot、PerplexityBot是放是拒,很多站从未主动决定过。放行意味着进入AI的引用池,拒绝意味着从AI的世界消失。两个选择都成立,但该由你拍板,别把它留给默认值。
第二件,把自己的盲区率跑出来。我的20页里盲区集中在长尾:白皮书PDF、2019年的老文、企业版定价页、about和contact。真实站点大概率同构——最想让AI引用的深度内容,往往恰恰最老、格式最偏。拿真实日志跑一遍,比任何"GEO优化秘籍"都实在。
第三件,把AI引荐单独记账。14/14的落库覆盖率说明规则表可用,豆包、Kimi、DeepSeek、文心一言与海外六家同权重。AI引荐和搜索引荐的转化路径完全不同,混在总流量里等于没有数据。
写在最后
上篇Gheist管"谁往我的仓库塞workflow",是CI入口的安全;这篇管"谁来读我的内容",是AI爬虫入口的可见性。两件事共享同一条叙事:日志里全都有答案,缺的是把答案翻出来的工具层。Gheist用base32骗过GitHub的日志脱敏,GEO这边的对称问题是——你的内容在AI眼里是否存在,比是否存在漏洞更隐蔽。SEO时代你至少知道去Search Console看一眼;GEO时代,先确认有没有人替你把日志翻出来,再确认翻得对不对——KimiBot那两笔消失的请求,就是后半句的答案。
数据核验说明
- 实验环境:Windows 11 + Docker Desktop 29.8.2(VM内存7.2GB),GEOInflow本地容器liekan:1.2.0(自构建镜像1.77GB,127.0.0.1:3002),底座Umami v3.4.1
- 投料:合成Nginx combined日志67行(gen_logs.py,固定种子,合成时间00:00~11:17 +0800);20页内容目录(catalog.csv);14条引荐事件走 /api/send浏览器口径
- 核验通道:crawler-recognition / crawler-analysis接口 + PostgreSQL直查website_event表
- 口径修正记录:首次采集于10:23运行,早于B/C/D组合成时间戳(10:30~11:17),首版快照不含伪装IP/未知UA/Chrome数据;当晚重采(只读接口),本文全部数字按全量数据修正。识别统计从首版26身份56请求变为重采26身份59请求,KimiBot漏报在两个时点一致存在
- B组IP来源:GPTBot官方段取自openai.com/gptbot.json(132.196.86.10),ClaudeBot官方段取自claude.com/crawling/bots.json(216.73.216.10);伪装IP为8.8.8.8 / 1.1.1.1 / 9.9.9.9
- 核验统计口径:12个身份24次请求被核验(verifiedRange 1次 + rangeMismatch 23次),其余14个身份35次请求unverified;identity findings按身份聚合共12条,各含小时窗与rangeMismatches计数
- 展示层口径:analytics population(traffic-quality-browser-population-v5)eligibleEvents=14、qualifiedPV=0;platforms接口81平台state=unknown/unsupported、visits=None;metrics referrer返回空数组
- 默认密码:liekan(tests/api/auth.spec.ts第51行),fork有意拒绝Umami upstream密码
- 构建故障:4次构建3次OOM(Next.js编译,Docker VM内存被14个实验容器挤占),第4次589.6s通过;DB-IP城市库构建期下载挂起6分钟,预下载mmdb兜底后构建291s;.env缺POSTGRES_USER/POSTGRES_DB报P2010启动循环
- 原始产物(access.log、events.json、results/api_results.json、verdict.py / dump2.py判定脚本)留档于ai-lab仓库
复现指引
配套代码与原始数据在 ai-lab仓库 的2026-10-27-geoinflow-geo目录:gen_logs.py生成合成日志,ingest.py投料,collector.py拉取识别与分析结果,verdict.py / dump2.py出六组判定与盲区清单。docker compose起容器后依次执行即可;做日志重放实验时让合成时间戳早于采集时刻,否则尾部数据不在快照里。
相关阅读
- 确定性刹车实测:agent说的每句话,先过工具这一关——本专栏第5篇
- 2300个插件没人把关:DSH插件市场实测——供应链审计视角的入口篇
- 腾讯AI-Infra-Guard实测——把供应链扫描做成平台工具的另一条路
- day-trader-skill实测——skill形态的fail-closed设计参考
- 博客导航文(全部实测文章索引)