GEO 可观测性,是通过 Web Server 日志、爬虫身份验证、AI 引荐流量和 Prompt 测试数据,判断生成式搜索系统有没有访问网站、访问了哪些 URL、是否被服务器拦截,以及访问之后是否进一步产生引用和点击。
它解决的是 GEO 中一个经常被忽略的工程问题:
页面发布以后,除了去 ChatGPT 搜一次,还有没有办法知道 AI 搜索系统到底访问过什么?
答案是有,但不能只看 GA4。
比较完整的数据链应该是:
AI Crawler ↓ Nginx / Apache Access Log ↓ Crawler Verification ↓ URL / Status / Frequency ↓ AI Search Citation ↓ Referral Click ↓ Analytics / Conversion
现有外贸 B2B GEO 体系中,也会把 AI 提及率、引用率、回答准确率以及数据归因单独作为监测层,而不是只用网站流量判断 GEO 效果。
本文重点解决前半段:
怎么从服务器日志观察 AI 爬虫。
为什么只看GA4看不到完整的GEO数据?
因为服务器抓取和真人访问不是同一种流量。
例如 OAI-SearchBot 请求:
GET /cnc-machining-tolerance/ HTTP/1.1 Host: example.com User-Agent: OAI-SearchBot/...
请求首先经过:
DNS ↓ CDN / WAF ↓ Nginx ↓ 应用服务器
它未必执行网页中的 GA4 JavaScript。
因此可能出现:
Nginx: OAI-SearchBot 今天访问了 187 次 GA4: 0 次
两边并不矛盾。
Web Analytics 更适合监测用户行为,而 Access Log 更适合监测 HTTP 请求。
可以这样区分:
| 数据 | Nginx日志 | GA4等分析工具 | Prompt测试 |
| AI爬虫访问 | ✓ | 通常不完整 | × |
| HTTP状态码 | ✓ | × | × |
| 请求URL | ✓ | 部分 | × |
| 爬虫IP | ✓ | × | × |
| AI是否引用页面 | × | × | ✓ |
| 品牌是否进入回答 | × | × | ✓ |
| ChatGPT带来的访问 | ✓ | ✓ | × |
| 页面停留/转化 | 部分 | ✓ | × |
所以一个比较重要的结论是:
Crawler Log ≠ GEO效果,但它是GEO技术可达性的底层证据。
现在应该监测哪些AI爬虫?
不能把所有名字里带 “AI” 的 User-Agent 当成同一种机器人。
截至 2026 年,不同平台已经把搜索抓取、模型训练和用户触发访问进一步拆开。
OpenAI有哪些爬虫需要区分?
至少应该区分:
| 标识 | 主要用途 | 是否等于ChatGPT搜索 |
| OAI-SearchBot | ChatGPT Search发现内容 | 更相关 |
| GPTBot | 潜在模型训练抓取 | 否 |
| 用户点击/引荐 | 真人访问网站 | 否 |
OpenAI 当前官方说明,网站希望内容能够进入 ChatGPT Search 的摘要和链接结果,应确保没有阻止 OAI-SearchBot;而希望内容不用于潜在模型训练,则可以单独限制 GPTBot。这两个控制目标并不相同。
因此日志中看到:
GPTBot
不能写成:
“ChatGPT 搜索今天抓取了这个页面。”
这是两种不同用途。
Perplexity有哪些访问类型?
Perplexity 当前至少公开了两个不同标识:
PerplexityBot Perplexity-User
官方对它们的定义也不同:
| 标识 | 用途 |
| PerplexityBot | 自动发现并建立搜索结果来源 |
| Perplexity-User | 用户提问过程中触发的页面访问 |
Perplexity 官方明确说明,PerplexityBot 不用于抓取基础模型训练数据;Perplexity-User 则属于用户主动触发的访问,并且后者通常不按照普通自动爬虫的 robots.txt 逻辑运行。官方还分别公布了对应 IP 范围。
这意味着日志分析时最好不要写:
Perplexity = PerplexityBot + Perplexity-User
然后全部计算成一个数字。
应该分开。
Google应该监测Googlebot还是Google-Extended?
这里最容易判断错误。
Google 当前明确说明:
Google-Extended 没有独立的 HTTP User-Agent 字符串。
它是 robots.txt 中用于控制 Gemini 相关训练和 grounding 使用方式的产品 token,实际抓取仍使用现有 Google User-Agent。并且 Google-Extended 不影响网站是否进入 Google Search,也不是 Google Search 的排名信号。
所以在日志中执行:
grep "Google-Extended" access.log
得到:
0
完全可能是正常现象。
对于 Google Search,应主要观察 Googlebot。Google 官方说明,Googlebot 的抓取规则影响 Google Search 及相关 Search 功能。
第一版Nginx日志应该记录哪些字段?
默认 Combined Log 可以使用,但做 GEO 可观测性时建议增加几个字段。
例如:
log_format geo_ai escape=json '{' '"time":"$time_iso8601",' '"remote_addr":"$remote_addr",' '"host":"$host",' '"method":"$request_method",' '"uri":"$request_uri",' '"status":$status,' '"bytes":$body_bytes_sent,' '"request_time":$request_time,' '"referer":"$http_referer",' '"user_agent":"$http_user_agent"' '}'; access_log /var/log/nginx/geo_ai.log geo_ai;
重新加载配置:
nginx -t systemctl reload nginx
一条日志可能变成:
{ "time": "2026-08-27T09:41:22+00:00", "remote_addr": "203.0.113.18", "host": "example.com", "method": "GET", "uri": "/guides/cnc-tolerance/", "status": 200, "bytes": 18342, "request_time": 0.082, "referer": "", "user_agent": "Mozilla/5.0 ... PerplexityBot/1.0 ..." }
比传统日志更方便后续进入:
jq Python Logstash ClickHouse 日志服务
做结构化分析。
怎么快速检查有没有AI爬虫访问?
如果还使用普通文本 access log,可以先通过 grep 粗查:
grep -Ei \ 'OAI-SearchBot|GPTBot|PerplexityBot|Perplexity-User|Googlebot' \ /var/log/nginx/access.log
统计次数:
grep -Eio \ 'OAI-SearchBot|GPTBot|PerplexityBot|Perplexity-User|Googlebot' \ /var/log/nginx/access.log \ | sort \ | uniq -c \ | sort -nr
假设得到:
1842 Googlebot 317 OAI-SearchBot 196 PerplexityBot 73 GPTBot 28 Perplexity-User
这个结果只能回答:
日志里出现了多少次相应 User-Agent。
还不能证明这些请求一定来自官方爬虫。
原因后面会讲。
用JSON日志怎么统计不同AI爬虫?
如果使用前面的 JSON Log,可以用 jq:
jq -r '.user_agent' geo_ai.log \ | grep -Ei \ 'OAI-SearchBot|GPTBot|PerplexityBot|Perplexity-User|Googlebot'
也可以直接统计:
jq -r '.user_agent' geo_ai.log | awk ' /OAI-SearchBot/ {openai_search++} /GPTBot/ {gptbot++} /PerplexityBot/ {perplexity++} /Perplexity-User/ {perplexity_user++} /Googlebot/ {googlebot++} END { print "OAI-SearchBot:", openai_search print "GPTBot:", gptbot print "PerplexityBot:", perplexity print "Perplexity-User:", perplexity_user print "Googlebot:", googlebot }'
第一阶段不需要复杂平台。
几十 MB 的日志直接用 Shell 就足够排查问题。
为什么不能只相信User-Agent?
因为 User-Agent 可以伪造。
任何普通 HTTP 客户端都可以发送:
User-Agent: OAI-SearchBot
甚至:
curl \ -A "Googlebot" \ https://example.com/
这时服务器日志一样会出现:
Googlebot
但请求显然不是 Google 发出的。
Google 官方因此明确警告,User-Agent 经常被其他爬虫伪造,验证 Googlebot 应结合官方 IP 范围或反向 DNS。
OpenAI 当前官方排障指南也建议不要只依赖短期日志里的 IP,应结合官方公布的 IP 范围、User-Agent、CDN Verified Bot 等信号;OAI-SearchBot 的 IP 范围可通过官方 searchbot.json 获取。
Perplexity 同样公开了 PerplexityBot 和 Perplexity-User 的 IP 列表。
因此更可靠的逻辑应该是:
User-Agent匹配 ↓ IP范围验证 ↓ CDN/WAF验证信号 ↓ Confirmed Bot
而不是:
User-Agent有Bot名字 ↓ 直接算官方流量
怎么用Python验证爬虫IP范围?
可以把平台公布的 CIDR 保存到本地,然后用 Python 的 ipaddress 判断。
例如:
import ipaddress crawler_networks = [ ipaddress.ip_network("192.0.2.0/24"), ipaddress.ip_network("2001:db8::/32") ] def is_verified_ip(ip_str): ip = ipaddress.ip_address(ip_str) return any( ip in network for network in crawler_networks ) print(is_verified_ip("192.0.2.21"))
注意:
上面的 CIDR 是文档示例地址,不是真实 OpenAI 或 Perplexity IP。
生产系统中应该定期同步各平台官方公布的 JSON,而不要从博客复制一份 IP 后永久写死。
OpenAI 当前也明确建议,如果系统确实需要稳定 IP 列表,应使用其官方发布的 searchbot.json。
GEO日志最应该统计哪些HTTP状态码?
最基本的是:
200 301 / 302 403 404 429 5xx
可以先建立这张解释表:
| 状态码 | 对AI抓取意味着什么 | 优先级 |
| 200 | 页面正常返回 | 正常 |
| 301/308 | 永久跳转 | 检查目标URL |
| 302/307 | 临时跳转 | 检查是否合理 |
| 403 | WAF/权限可能阻止 | 高 |
| 404 | 请求URL不存在 | 中 |
| 429 | 请求触发限速 | 高 |
| 5xx | 服务端失败 | 高 |
OpenAI 当前官方排障文档特别指出,WAF 或 Bot Mitigation 很容易误伤自动抓取并返回 403 Forbidden;如果存在 Rate Limit,则应重点排查 429 Too Many Requests。
例如:
OAI-SearchBot 200: 430 403: 187 429: 96
此时单看:
713 次访问
会得出“抓取很活跃”的错误结论。
真正有效的 2xx 访问只有:
430 / 713 ≈ 60.3%
这个数字才更有排障意义。
怎么用Python生成AI爬虫状态报告?
假设 JSON 日志为:
/var/log/nginx/geo_ai.log
可以写一个简单脚本:
import json from collections import Counter, defaultdict BOT_PATTERNS = { "openai_search": "OAI-SearchBot", "openai_training": "GPTBot", "perplexity_search": "PerplexityBot", "perplexity_user": "Perplexity-User", "google_search": "Googlebot" } stats = defaultdict(Counter) with open( "/var/log/nginx/geo_ai.log", "r", encoding="utf-8" ) as f: for line in f: try: row = json.loads(line) except json.JSONDecodeError: continue ua = row.get("user_agent", "") status = str(row.get("status", "")) for bot_name, pattern in BOT_PATTERNS.items(): if pattern.lower() in ua.lower(): stats[bot_name][status] += 1 for bot_name, values in stats.items(): total = sum(values.values()) print(f"\n{bot_name}") print(f"total = {total}") for status, count in values.most_common(): ratio = count / total * 100 print( status, count, f"{ratio:.2f}%" )
结果可能类似:
openai_search total = 713 200 430 60.31% 403 187 26.23% 429 96 13.46% perplexity_search total = 284 200 270 95.07% 404 14 4.93%
这时就能非常快速地看到:
PerplexityBot 基本正常,但 OAI-SearchBot 被基础设施大量阻止。
这种结论比“ChatGPT 为什么不收录我们?”更容易定位问题。
哪些页面最值得检查AI抓取频率?
不能只统计爬虫总次数。
还应该查看 Top URL。
例如 Python:
import json from collections import Counter urls = Counter() with open("geo_ai.log", encoding="utf-8") as f: for line in f: row = json.loads(line) ua = row.get("user_agent", "") if "OAI-SearchBot" in ua: if int(row["status"]) == 200: urls[row["uri"]] += 1 for url, count in urls.most_common(20): print(count, url)
结果:
52 /robots.txt 37 /sitemap.xml 31 /blog/ 28 /guides/cnc-machining/ 26 /guides/cnc-tolerance/ 4 /products/aluminum-housing/ 1 /cases/medical-device/ 0 /solutions/semiconductor/
这时可以提出一个更具体的问题:
为什么技术文章被反复抓取,而核心 Solution 页面几乎没有被访问?
下一步再检查:
是否有内链? 是否进入Sitemap? 是否被canonical到其他URL? 服务器是否返回异常? URL层级是不是过深?
这才是可操作的 GEO 排查。
应该把哪些字段存进GEO日志表?
如果要长期保存,不建议只存一列 User-Agent。
可以设计:
CREATE TABLE ai_crawl_event ( event_time DateTime, provider String, crawler_type String, verified UInt8, remote_ip String, host String, method String, url String, status UInt16, response_bytes UInt64, request_time_ms Float32, referer String, user_agent String );
其中比较重要的是:
provider crawler_type verified status url event_time
例如:
| provider | crawler_type | verified |
| OpenAI | Search | 1 |
| OpenAI | Training | 1 |
| Perplexity | Search | 1 |
| Perplexity | User Fetch | 1 |
| Unknown | OAI UA Spoof | 0 |
这样后面才能区分真实访问和伪造 User-Agent。
GEO爬虫监控应该看哪些指标?
第一版 Dashboard 不需要几十个指标。
建议先做 8 个:
| 指标 | 计算方式 | 用途 |
| Verified Requests | 官方爬虫请求数 | 实际访问规模 |
| 2xx Rate | 2xx / 总请求 | 成功抓取比例 |
| 403 Rate | 403 / 总请求 | WAF阻断 |
| 429 Rate | 429 / 总请求 | 限流情况 |
| Unique URLs | 被访问URL去重数 | 内容覆盖 |
| Fresh URLs Crawled | 新页面抓取量 | 新内容发现 |
| Avg Response Time | 平均请求耗时 | 服务性能 |
| Crawl Distribution | 不同目录占比 | 抓取结构 |
例如:
过去7天: OAI-SearchBot ------------------------ Requests 2,431 2xx Rate 94.2% 403 Rate 2.1% 429 Rate 1.7% Unique URLs 386 New URLs 47 Avg Time 84 ms
这已经足够回答许多技术问题。
怎么判断爬虫是不是只在重复访问无价值页面?
可以按 URL 前缀聚合。
例如:
| 目录 | 请求次数 | 占比 |
| /blog/ | 1430 | 58.8% |
| /products/ | 392 | 16.1% |
| /guides/ | 354 | 14.6% |
| /solutions/ | 133 | 5.5% |
| /cases/ | 122 | 5.0% |
如果:
/blog/tag/ ?page= ?sort= ?utm_
等低价值 URL 占据大量请求,则应该检查:
参数URL 分页 Faceted Navigation Canonical 内部链接 Sitemap
这属于传统 Crawl Management,但在 GEO 环境下仍然有效。
Google 2026 年的官方 GEO 指南也再次强调,生成式 AI Search 仍建立在现有 Search 基础设施之上,技术 SEO 基础并没有因为 AI 搜索出现而失效。
服务器日志能证明页面被AI引用了吗?
不能。
这是 GEO 日志分析最重要的边界。
日志能够证明:
某个请求 在某个时间 访问了某个URL 服务器返回了什么
不能证明:
页面进入了最终答案
例如:
2026-08-27 OAI-SearchBot GET /cnc-guide/ 200
它只能说明某个匹配并验证后的 SearchBot 请求访问了页面。
不能进一步写成:
“ChatGPT 今天引用了 CNC Guide。”
这需要通过 Prompt 监测或实际答案数据判断。
那怎么知道ChatGPT真的带来了用户?
这里要看 Referral。
OpenAI 当前官方说明,当用户从 ChatGPT Search 的结果进入外部网站时,引荐 URL 会自动带上:
utm_source=chatgpt.com
网站可以通过分析系统识别对应流量。
例如:
https://example.com/cnc-guide/ ?utm_source=chatgpt.com
因此完整的数据应该分三类:
Crawler Data AI有没有访问网站? Citation Data AI有没有使用网站? Referral Data 用户有没有点击网站?
三者不要合并。
一套完整的GEO可观测架构应该怎么搭?
一个中小型站点可以从非常简单的架构开始:
┌─ OAI-SearchBot ├─ PerplexityBot Internet ────┼─ Googlebot └─ Other Crawlers ↓ CDN / WAF ↓ Nginx ↓ JSON Access Log ↓ ┌─────────┴─────────┐ ↓ ↓ Bot Verification URL Analysis ↓ ↓ CIDR/IP Status / Frequency └─────────┬─────────┘ ↓ GEO Dashboard ↓ Prompt Monitor / Analytics
如果网站每天只有几万次请求:
Nginx + Python + Cron
就已经可以工作。
如果达到:
数百万请求/天
再考虑:
Filebeat / Fluent Bit ↓ Kafka ↓ ClickHouse / Elasticsearch ↓ Grafana
或者接入已有云日志体系。
不要为了 GEO 一开始就搭一套复杂大数据平台。
GEO可观测性和传统SEO日志分析有什么区别?
技术基础基本相同,但关注对象有所扩展。
| 维度 | SEO日志分析 | GEO日志分析 |
| Googlebot | 核心 | 仍然核心 |
| AI Search Bot | 很少关注 | 重点 |
| Training Bot | 通常不区分 | 需要区分 |
| User-triggered Fetch | 很少出现 | 需要单列 |
| 搜索点击 | Search Console | 还需AI Referral |
| 排名 | Keyword | Prompt / Citation |
| 核心问题 | 搜索能否抓取 | 搜索+AI能否发现 |
| 最终结果 | SERP | SERP + AI Answer |
所以 GEO 可观测性并不是抛弃 SEO 日志分析重新发明一套东西。
更合理的做法是:
在已有 Web Observability 上增加生成式搜索维度。
为什么Google-Extended特别容易统计错?
因为它是 robots.txt Product Token,而不是独立请求 User-Agent。
Google 官方当前描述非常明确:
Google-Extended 没有独立HTTP User-Agent
并且它管理的是 Google 已抓取内容是否可以进一步用于:
未来Gemini模型训练 Gemini Apps grounding Vertex AI相关用途
它不会决定网站是否进入 Google Search。
因此这样的 Dashboard:
Google AI Crawl = grep Google-Extended
从设计上就是错误的。
应该把:
Crawl Identity
和:
robots Product Control
分开管理。
GEO日志监控最常见的错误有哪些?
第一种是:
看到 User-Agent = 认为是真实官方爬虫
忽略 IP 验证。
第二种是:
看到爬虫访问 = 认为页面已被AI引用
混淆 Crawl 与 Citation。
第三种是:
Google-Extended没日志 = Gemini没有访问
忽略 Google-Extended 并没有独立 HTTP User-Agent。
第四种是:
只统计200数量
但没有同时检查:
403 429 404 5xx
第五种是:
只看请求总量
却不知道访问的到底是:
robots.txt tag页面 参数URL 还是核心内容页
FAQ:GEO爬虫日志还有哪些问题需要注意?
日志里出现OAI-SearchBot,就说明页面会进入ChatGPT答案吗?
不说明。
它只能证明相应 User-Agent 的请求访问过网站;进一步还需要验证 IP 身份。
即使确认是真实 OAI-SearchBot,也只能证明页面被访问,不能证明页面最终被选为引用来源。
OAI-SearchBot和GPTBot应该合并统计吗?
不建议。
OpenAI 官方把二者用于不同控制目标:OAI-SearchBot 与 ChatGPT Search 的内容发现相关,而 GPTBot 对应潜在模型训练用途。
因此数据表最好分别记录:
OpenAI / Search OpenAI / Training
网站不允许GPTBot,会影响ChatGPT Search吗?
按照 OpenAI 当前公开说明,这两个控制是分开的。
如果目标是允许 ChatGPT Search 发现页面,应关注是否允许 OAI-SearchBot;是否允许 GPTBot 则属于模型训练数据使用控制。
为什么日志里有大量403?
优先检查:
WAF CDN Bot Protection IP黑名单 Geo Block JavaScript Challenge CAPTCHA 应用鉴权
OpenAI 官方也把 WAF、Bot Mitigation、CAPTCHA 和其他 Human Verification 机制列为爬虫访问失败的主要排查环节。
429很多应该直接关闭限流吗?
不建议。
更合理的是确认:
请求是否真实 请求频率 命中的URL IP是否经过验证 当前限流规则
再决定是否对经过验证的合法爬虫设置单独策略。
没有必要因为看到一个可疑 User-Agent 就全局取消服务器保护。
Googlebot也需要验证IP吗?
需要。
Google 官方明确提醒 Googlebot User-Agent 可以被伪造,推荐通过官方 IP 范围或者 reverse DNS 验证请求身份。
需要每天人工查看日志吗?
不需要。
可以建立每日任务,只输出异常:
2xx Rate < 90% 403 Rate > 5% 429突然增加 核心目录连续7天无访问 新页面长期未抓取 未知AI Bot请求激增
这里的阈值应该根据站点自己的历史基线确定,上面的数字只是报警策略示例,不是行业统一标准。
服务器日志能替代GEO Prompt测试吗?
不能。
两者分别回答不同问题:
日志: AI有没有来? Prompt测试: AI回答时有没有用你?
真正完整的监测体系需要同时保留二者。
GEO为什么最终需要“可观测性”?
GEO 如果无法观测,很容易变成靠感觉优化。
运营人员可能看到:
ChatGPT没出现品牌
然后判断:
内容写得不好。
但服务器实际情况可能是:
OAI-SearchBot 403 Rate = 81%
这时继续改文章并不能解决核心问题。
另一个网站可能是:
OAI-SearchBot 2xx Rate = 99% 核心页面全部被访问
但 Prompt 测试:
Citation Rate = 4%
此时问题显然已经从:
Crawlability
转向:
Retrieval Citation Content Quality Entity Understanding
因此,可以把 GEO 故障定位划成四层:
Layer 1 能不能访问? → Nginx / WAF / HTTP Layer 2 访问了什么? → Crawl Log Layer 3 有没有进入答案? → Prompt / Citation Monitor Layer 4 用户有没有点击并转化? → Analytics / CRM
只有把这四层拆开,团队才能判断一次 GEO 异常究竟发生在哪个环节。
传统 SEO 很早就形成了 Search Console、Server Log、Analytics 等数据体系。生成式搜索出现以后,GEO 同样需要建立自己的 Observability,而不是每周人工问 ChatGPT 几个问题。
对于开发者来说,第一步甚至不需要购买新的 GEO 工具。
从服务器已经存在的:
access.log
开始,把 User-Agent、IP、HTTP Status、URL 和请求时间结构化记录下来,就已经能回答一个非常实际的问题:
AI搜索系统到底有没有真正访问过我的网站?
当这个问题能够被日志和数据回答时,GEO 才真正从“内容经验”进入可排查、可验证的工程流程。