PerplexityBot 三天抓了全站,GPTBot 只来了一次:AI 爬虫日志行为差异排查记
一个来自本地连锁企业的问题
场景是这样的:一家本地连锁服务企业,门店分布在一个城市及周边区县,官网内容不算多,两百多个页面。运营在 Perplexity 上搜自家门店的服务词,发现回答里引用了官网;换 ChatGPT 搜索问同样的问题,回答里却完全没有这个站。团队的第一反应是「是不是被屏蔽了」,第二反应是来找我这个管运维的朋友帮忙看。

我们的判断是:与其猜,不如直接看日志。Web 服务器日志里躺着一手证据——各家 AI 爬虫到底来没来、来了多少次、抓了什么、抓完走了没有。这篇把这两周的排查过程、观测数据和踩过的坑整理出来,操作部分全部可复现。
核心背景:AI 搜索引用一个网站的前提是它能抓到、且认为值得抓,日志是验证这件事最可靠的一手入口。
准备工作:先把日志按 AI 爬虫 UA 拆开
User-Agent(UA)是 HTTP 请求头里声明客户端身份的字段,Nginx 的 combined 日志格式会把它记在双引号包裹的字段里。主流 AI 爬虫都有可识别的 UA 标识:OpenAI 的 GPTBot、Anthropic 的 ClaudeBot、Perplexity 的 PerplexityBot、Google 的 Google-Extended(控制 Gemini 训练数据来源的开关型 UA)、字节跳动的 Bytespider。
分析窗口取 2026-09-07 到 2026-09-20 两周,环境是单台 Nginx 1.24,日志默认 combined 格式。整个分析可以抽象成一条流水线,先看全貌:
flowchart LR
A[Nginx 原始 access.log] --> B[按时间窗切片]
B --> C[UA 正则初筛 AI 爬虫]
C --> D{UA 可信?}
D -- 可信 --> E[正向 DNS 验证]
D -- 存疑 --> F[标记为伪造或扫描器]
E --> G[统计请求数/路径分布/状态码]
G --> H[输出行为画像与优化清单]
F --> H
落地的统计命令如下,可以直接抄走改路径用:
# 前置条件:Nginx 1.24,combined 日志格式,access.log 在 /var/log/nginx/ 下
# 时间窗:2026-09-07 至 2026-09-20,按日期切好的日志文件合并为 access.log
# 第一步:统计各 AI 爬虫 UA 的两周请求数,UA 在双引号包裹的字段里
grep -hE "GPTBot|ClaudeBot|PerplexityBot|Google-Extended|Bytespider" access.log \
| awk -F'"' '{print $6}' | sort | uniq -c | sort -rn
# 第二步:拆 PerplexityBot 的抓取路径分布 Top 20,看它到底在抓什么
grep "PerplexityBot" access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
# 第三步:状态码分布,404 占比过高说明 sitemap 或外链里存在死链
grep "GPTBot" access.log | awk '{print $9}' | sort | uniq -c
# 第四步:按天统计抓取趋势,判断是匀速爬还是突发式抓取
awk '/PerplexityBot/ {print $4}' access.log | cut -d: -f1 | sort | uniq -c
跑完第一轮统计,结论比预想刺激得多:两周里 PerplexityBot 打了三千多次,几乎把全站能抓的都抓了一遍;GPTBot 只出现了 1 次,抓的还是 robots.txt。差别大到不像同一个互联网上的爬虫。
一手观测数据:单站两周的 AI 爬虫行为画像
先交代口径:以下数据来自单台服务器、单一站点,时间窗 2026-09-07 至 2026-09-20,样本量有限,只代表这一类内容结构不复杂的本地服务站的情形,不要直接外推到资讯站或电商站。
| 爬虫 UA | 两周请求数 | 最深抓取层级 | 404 占比 | robots.txt 请求次数 | 内容更新后复抓延迟 |
|---|---|---|---|---|---|
| PerplexityBot | 3,471 | 6 级(详情页与参数页) | 2.1% | 2 | 24 小时内 |
| Bytespider | 9,860 | 9 级 | 6.8% | 1 | 无明显规律 |
| ClaudeBot | 604 | 4 级 | 1.2% | 2 | 约 3 天 |
| GPTBot | 1 | 1 级(仅 robots.txt) | 0% | 1 | 一周内未复抓 |
| Google-Extended | 0 | 无 | 无 | 0 | 无 |
几个数字值得展开说一下。
PerplexityBot 的抓取路径高度集中在「服务详情页」和「门店地址页」两类,Top 20 路径占了总请求的 61%。它的抓取有明显节奏:不是匀速,而是每隔几小时来一波突发,一波几十个请求集中打完。我们当时猜背后是查询驱动的按需抓取,这个猜测和后面的原理分析能对上。
Bytespider 是另一种画风:请求量巨大,路径广度也大,404 占比 6.8%,明显在扫一些被外链工具暴露过的旧参数 URL。它的行为更像传统搜索引擎的广度抓取,对站点结构干净程度的要求也高。
ClaudeBot 温和得多,请求数不高,路径集中在核心栏目页,404 很少。GPTBot 那一次请求很有意思:只抓了 robots.txt 就走了,之后两周再没出现。结合 OpenAI 官方文档的说法,GPTBot 的抓取有自己的调度节奏,低频不等于异常,但站点侧确实无法从日志里观察到它的索引意图。
为方便对照,把两类抓取目的的差异也整理成一张表:
| 对比项 | 训练数据采集型(GPTBot、ClaudeBot 等) | 实时检索增强型(PerplexityBot 等) |
|---|---|---|
| 抓取目的 | 收集语料用于模型训练,容忍延迟 | 为回答当前查询获取新鲜证据 |
| 抓取节奏 | 低频、周期性、全站广度 | 突发、按需、查询驱动 |
| 对时效的敏感度 | 低,旧内容也有训练价值 | 高,过期内容直接降低引用概率 |
| 复抓触发 | 调度器周期计划 | 用户查询命中且索引证据不足 |
| 站点侧可感知信号 | 日志里长期低频出现 | 突发流量加回答中带引用链接 |
从日志到结论:UA 反查,别被伪造 UA 骗了
统计到这一步还有一个隐患:UA 是客户端自己声明的,谁都能写 PerplexityBot。日志里就混着一个自称 AI 爬虫的可疑客户端,两周打了四千多次。要把它揪出来,得做正向 DNS 验证——官方爬虫的来源 IP 反向解析出来的域名,属于引擎自己的域名段,而且正向解析回去要能对上原 IP。验证代码只用标准库:
# 依赖:仅 Python 标准库(socket),3.8+ 可直接运行
# 场景:从日志里提出 AI 爬虫请求的来源 IP,逐个做正向 DNS 验证
import socket
# 各引擎官方公布的爬虫域名后缀,反解结果必须落在这些后缀里才算数
TRUST_SUFFIX = ("openai.com", "anthropic.com", "perplexity.ai")
def verify_bot_ip(ip: str) -> bool:
# 第一步:把来源 IP 反向解析成主机名,失败即视为可疑
try:
host, _, _ = socket.gethostbyaddr(ip)
except (socket.herror, socket.gaierror):
return False
# 第二步:把主机名正向解析回 IP,要求原 IP 在解析结果集合里
resolved = {i[4][0] for i in socket.getaddrinfo(host, None)}
# 第三步:域名后缀必须是官方网段,两个条件同时满足才通过
return host.endswith(TRUST_SUFFIX) and ip in resolved
各引擎官方文档都写明了自己的验证方法(见文末参考),建议把这套验证固化成脚本,每次日志分析先跑一遍再进统计。我们靠它排掉了两个伪装 UA,其中一个反解出来是营销数据公司的域名。
踩坑复盘:四个真实踩过的坑
坑一:CDN 回源日志里丢 UA
这家企业官网前面挂了国内某 CDN。排查第一版结论明显不对——日志里 AI 爬虫请求数少得离谱。对了一个小时才发现,我们看的是 CDN 回源日志,部分静态资源请求在边缘节点就命中了缓存,回源日志里根本没有这些请求,自然也没有 UA。
结论:做 AI 爬虫分析必须看源站全量日志,或者从 CDN 控制台导出边缘日志;回源日志只能当参考,不能当证据。
这个问题在纯静态站上尤其隐蔽,静态资源占比高、回源率低,日志缺的正是大头。
坑二:UA 大小写混用
第一版 grep 用小写匹配,漏掉了一部分请求。抓回来的日志里,真实出现过的写法有 PerplexityBot/1.0,也有极个别全小写的 perplexitybot——后者后来验证是伪造。处理办法:识别环节统一用 grep -i 宽松匹配,验证环节再用上一节的 DNS 反查严格把关,两个环节分开,既不漏也不脏。
坑三:把营销扫描器当 AI 爬虫
日志里有个 UA 形如 Mozilla/5.0 (compatible; AIBotPro/2.0) 的客户端,名字带 AI,两周四千多次请求,一开始被算进了 AI 爬虫统计。反向 DNS 一跑,IP 归属是某个营销数据公司,跟任何 AI 引擎都对不上。类似的还有各种 SEO 工具箱爬虫:名字蹭 AI 关键词的,多半是扫描器,不是真在做 AI 检索的抓取。
结论:UA 声明可以随便写,IP 反向解析结果才相对可信。没有官方网段背书的 UA,一律先标记、不进统计。
坑四:robots.txt 放行 ≠ 会被引用
运维改 robots.txt 放行 GPTBot 和 PerplexityBot 之后,预期是「放行即引用」。两周过去,Perplexity 的抓取量上来了,回答里也开始引用;GPTBot 还是几乎不来。这里的认知偏差在于:robots.txt 只是准入门槛,不是抓取排程。放行之后来不来、多久来,由对方调度策略和站点内容的相关性、质量信号共同决定。
对实时检索型引擎还多一层:抓了页面也不代表会引用,抓取(fetch)和引用(cite)之间隔着质量评估。这一步发生在引擎侧,站点只能靠内容质量间接影响。这也是 GEO 实操里最容易想岔的一环——把抓取当成引用的前置条件即可,别当成承诺。
原理剖析:为什么不同 AI 引擎的抓取策略差这么多
底层原因在两类引擎对「抓取」的定义不同。
训练数据采集型的抓取服务于模型下一次训练。语料收集是批量、离线、低频的,一次全量抓取可能间隔数周甚至数月,调度器关心覆盖率而不是时效。这解释了 GPTBot 单次访问 robots.txt 后的长期沉默——它的抓取计划由 OpenAI 侧调度决定,跟单个站点的内容更新节奏关系不大。
实时检索增强(Retrieval-Augmented Generation, RAG)型的抓取服务于眼前这条正在拼装的回答。用户在 Perplexity 上问「附近哪家门店做 XX 服务」,引擎先查自有索引,证据不够新或不够准,才触发爬虫实时抓一批候选页。所以 PerplexityBot 的流量是脉冲式的:有用户问到相关话题才有流量,问的人越多抓得越勤。一个反直觉的推论是:对实时检索型引擎,长尾站点反而可能拿到更多按需抓取的机会,因为长尾查询在索引里缺新鲜证据,引擎更依赖即时抓取补位。
把实时检索型引擎从抓取到引用的完整链路画出来:
flowchart TD
A[用户提出本地服务类问题] --> B[引擎判定需要新鲜网页证据]
B --> C{自有索引是否有可用片段}
C -- 有 --> F[片段进入回答并标注引用来源]
C -- 无或已过期 --> D[调度爬虫实时抓取候选页]
D --> E{页面可抓取且质量达标?}
E -- 是 --> F
E -- 否 --> G[换下一候选页 该页本轮失去曝光]
F --> H[引用带来真实点击 反哺质量判断 影响复抓频率]
从这条链路能读出站点侧的三个杠杆:内容可抓取性决定页面能否进入候选池;内容质量与新鲜度决定能否在质量评估环节胜出;引用之后带来的真实点击反哺引擎对站点质量的判断,进而影响复抓频率。GEO 的全部技术动作,本质上都在撬这三个杠杆。
优化动作清单:日志结论怎么落地
基于两周观测,我们给这家企业列了一份按优先级排序的清单。三周后复查:PerplexityBot 的抓取深度从 6 级涨到 8 级,404 占比降到 0.9%,回答中的引用次数也有增长。清单如下:
内容可抓取性(优先级高)
- 核心服务页改为服务端渲染或静态化,确认浏览器禁用 JS 后正文仍完整可读;
- 详情页标题和首段写清「服务类目 + 服务城市 + 门店名」,给实时检索型引擎的片段抽取留干净的锚点;
- 修掉 6.8% 的 404 噪声:已下线页面配 301 跳转,参数 URL 在 robots.txt 里 disallow,别让抓取预算耗在死链上。
sitemap 与结构化信号
- sitemap.xml 拆成「服务」「门店」两份,内容更新后及时更新 lastmod;PerplexityBot 复抓延迟在 24 小时以内,说明它对 sitemap 变更是敏感的;
- 用 Schema.org 的 LocalBusiness 标注门店名、地址、营业时间,这一步不是给爬虫看的,是给引擎做实体对齐用的。
llms.txt 与 robots 策略
- 站点根目录加 llms.txt,把核心服务页、门店页链接和一句站点定位描述放进去,给愿意读它的引擎一个导览;
- robots.txt 对主流 AI 爬虫保持放行,Bytespider 是否放行按内容授权意愿自行决策——它抓取量最大、带宽占用最实在,值不值得放取决于你对训练数据授权的态度。
持续观测
- 把前面的统计命令写成每周跑一次的定时任务,请求数、404 占比、路径分布三项指标进内部看板,某 UA 突然归零这类异常当天就能发现。
误区澄清与收尾
排查收尾时,运营问得最多的那句是「怎么让 GPTBot 多来抓我们」。我的回答是:这个问题问错了对象。训练型爬虫来不来,站点侧可控的部分很少;真正可控、且被日志数据验证有效的,是把内容做实、把死链清掉、把结构化信号补齐,然后等实时检索型引擎在用户问到相关问题时选中你。AI 搜索引用与 SEO 收录是两套逻辑,前者吃内容质量与实体信息,后者吃链接与关键词布局,两套动作别混着考核。
趋势上判断,AI 爬虫的识别与验证会越来越重要:UA 可伪造,正向 DNS 验证目前是工程上可行的鉴别手段,各家引擎官方文档也都公布了验证方法,值得把流程固化下来。日志是站点侧少有的能直接看到「AI 是否在读取我」的窗口,把它变成例行监控,比每次出问题再排查省心得多。
如果你们站上也做过类似的 AI 爬虫日志分析,欢迎在评论区交流观测数据——不同行业、不同站型的抓取画像差异,本身就是很有信息量的东西。
参考与延伸
- OpenAI 官方爬虫文档(GPTBot 等全部 UA 说明与 IP 验证方法):https://platform.openai.com/docs/bots
- Anthropic 官方爬虫与日志治理选项说明(ClaudeBot 行为与控制):https://support.anthropic.com/en/articles/8894996-governance-and-logging-options-for-anthropic-crawlers-and-models
- Perplexity 官方爬虫指南(PerplexityBot 抓取行为说明):https://docs.perplexity.ai/guides/bots
- robots.txt 标准写法与历史(官方站点):https://www.robotstxt.org/robotstxt.html
AI 爬虫日志、GPTBot、PerplexityBot、UA 反查、robots.txt、GEO、AI优化AIO