log file analysis 怎么做:从服务器日志看 AI 爬虫到底来没来
log file analysis 读的是服务器早就替你记下的两列:User-Agent 和 IP。这一章给一条能直接粘的命令、一张字段表、一张令牌表,以及怎么判断哪些行可以相信。

log file analysis 指的是去读服务器早就替你记下来的那两列:User-Agent 和 IP。它回答的问题,和「用伪造 UA 去请求一次」完全不同。后者告诉你门能不能推开,前者告诉你到底谁进来过、哪天来的、来了几次。一次 200 只说明门是开的。日志才说明有人走进去。
读这篇之前
你需要一份服务器访问日志的读取权限——nginx、Apache、Caddy,或者托管商后台能导出日志——外加一个终端。前提就这一条。如果你的托管商不给日志,这一章没有替代方案:任何第三方工具都看不到你服务器上的原始请求,因为它们根本没到过你的服务器。
旁边有两章和这一章连着读。如果你还没确认过 AI 爬虫能不能抓到你,先看 怎么查 AI 能不能抓取你的站,那一篇是从站外把门推开试一次。如果你想看的是「外面测完之后到底来了谁」的实测版本,那是另一篇:AI 爬虫实际读到了什么,里面是我们拿五个站跑的 85 次请求。
log file analysis 能回答什么,不能回答什么
它能告诉你:哪些 User-Agent 请求了哪些路径、什么时间、返回什么状态码、来自哪个 IP。它不能告诉你内容后来有没有被用在回答里、有没有进训练集。它也不能单独确认身份——User-Agent 是客户端自己报的,谁都能抄。只有 IP 对得上,才把「一条自称 GPTBot 的请求」变成「GPTBot」。
这个区别就是它值得单独成章、而不是一句提示的原因。一行日志有两个半边。大家都会看的那半边是 User-Agent。决定这行能不能信的那半边是 IP。
为什么日志比 UA 自检更硬
可达性自检和日志量的是两件事,而大部分错结论就长在两者的缝里。自检是你发一个带着伪造 UA 的请求,看你的技术栈怎么响应。日志是真实客户端主动发起的请求,你没让它来。
两边会往相反的方向打架。你可能自检通过、却一直没有 AI 爬虫流量,因为「能到达」不等于「会来」。你也可能自检失败、日志里却有爬虫,因为自检走的路径未必是爬虫走的路径——CDN 的边缘规则完全可能把来自机房 IP 的 HEAD 请求,和来自真爬虫的 GET 请求区别对待。
日志还带着一个自检永远产不出的字段:时间。自检给你某一刻的是或否。日志给你每个 bot 每天的条数——这是唯一能把「每周来一次」和「来过一次就再没来」分开的办法。
按这个顺序做
五步。每一步都有一个能先验的完成标志,没验过不要往下走。
- 先找到日志、确认格式。nginx 默认是
combined格式,Apache 是 NCSA extended/combined 格式。Apache 官方文档把两者写成%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i",最后一个引号里是 User-Agent,倒数第二个引号里是来源页。完成标志:你能指着任意一行,逐个字段说出它是什么。 - 先别过滤,按 User-Agent 全量数一遍。把 combined 格式的行按引号切分,User-Agent 落在第 6 段。完成标志:你手上有一份访问过本站的全部 agent 的前 30 名,而不是你预期会来的那几个。
- 再把 AI 爬虫的令牌挑出来。具体字符串见下面那张表。完成标志:每个令牌都有一列请求数和一个首次出现日期。
- 核实你打算相信的那些 IP。Google 走反查,OpenAI 走公布的 IP 段清单。完成标志:你准备写进结论的每一行,要么通过了「正反查一致」的校验,要么被明确标成未验证。
- 记下时间窗,不只记总数。没有天数,一个数字什么也说明不了。完成标志:你的记录长这样「412 次请求,2026-08-01 到 2026-08-31,5 个站」,而不是「挺多的」。
交付物:一条命令 + 两张表
下面这条命令,把一份 combined 格式日志变成「每个来过本站的 agent 各多少次」。它假设 User-Agent 字段里没有转义引号——对下面这些爬虫成立,对某些采集器不成立。
awk -F'"' '{print $6}' access.log \
| sed 's/;.*compatible;//' \
| sort | uniq -c | sort -rn | head -30
那句 sed 是因为浏览器型 UA 会把真正的产品令牌埋在一长串兼容前缀后面。它切得很粗,所以原始的第 6 段也要留一份——当某个计数看着不对时,你得能退回去看原文。
第二件交付物是字段表。多数人只知道 User-Agent 那一列就停了,所以第一遍常常漏掉路径。
| 字段 | 长这样 | 说明什么 |
|---|---|---|
| 来源 IP | 66.249.66.1 | 唯一能和公开清单核对的字段 |
| 请求行 | GET /pricing HTTP/1.1 | 抓了哪一页——方法和路径 |
| 状态码 | 200 | 爬虫拿到的是内容还是被挡 |
| 返回字节 | 18432 | 大致返回了多少内容 |
| 来源页 | - | 爬虫请求里这一列几乎永远是空的 |
| User-Agent | ... GPTBot/1.4 ... | 自报身份,可伪造,也是被过度相信的一列 |
第三件交付物是令牌清单。下面是各家运营方自己文档里公布的写法,2026-09-22 逐个实取。它不是全部 AI 爬虫的名单,新的爬虫随时出现、不会通知你——这正是第 2 步要先把所有 agent 全量数一遍的原因。
| 令牌 | 运营方 | 用途 | 可验证 |
|---|---|---|---|
GPTBot | OpenAI | 训练抓取 | 可——openai.com/gptbot.json |
OAI-SearchBot | OpenAI | 搜索呈现 | 可——openai.com/searchbot.json |
ChatGPT-User | OpenAI | 用户触发 | 可——openai.com/chatgpt-user.json |
Googlebot | 搜索抓取 | 可——反查加 common-crawlers.json | |
Google-Extended | 训练控制令牌 | 它不是爬虫,自己不发请求 | |
ClaudeBot | Anthropic | 抓取 | 有文档,IP 段以它自己页面为准 |
PerplexityBot | Perplexity | 抓取 | 有文档,IP 段以它自己页面为准 |
表里有两行是承重的。Google-Extended 是控制令牌不是爬虫:Google 文档原话是它「doesn't have a separate HTTP request user agent string」,所以它永远不会出现在你的日志里,它的缺席不是失败。而 ChatGPT-User 由真人触发,同一份文档写它「is not used for crawling the web in an automatic fashion」,它的请求不是自动抓取。
哪里最容易做错
你信了 User-Agent。这是默认错误,而且它会给你一个很自信、但是错的答案。谁都能在请求头里写 GPTBot/1.4,采集器也确实这么干。Google 自己的指引写得很死:验证就是两次 DNS 查询——先对 IP 反查,再对返回的域名正查,两次必须对上。OpenAI 这边则是把 IP 拿去和公布的段清单匹配。至于两边都不公布的爬虫,你验证不了,诚实的做法是在计数旁边写「未验证」,而不是把它删掉或者照单全收。
你把 robots.txt 的抓取算成了页面抓取。OpenAI 文档提到,抓 robots.txt 时它「may add a robots.txt marker to the user-agent string to help site owners distinguish those requests from requests for other resources, especially when logs do not include paths」。如果你的日志格式丢掉了路径,一次 robots.txt 抓取和一次页面抓取长得一模一样。报数之前先按路径拆开。
你读的窗口太短。七天的日志回答不了三十天的问题,而日志轮转会在没有任何提示的情况下把窗口截短。写清楚你实际数到的第一条和最后一条时间戳,而不是你本想统计的那段时间。
常见问题
日志里的 User-Agent 能不能信?
不能。在 IP 对上公开清单、或者通过正反查一致的校验之前,它只是一个声明。日志是记录,不是证据。
怎么确认 GPTBot 真的来过我的站?
先在日志里 grep 令牌 GPTBot,再把命中的每个 IP 拿去和 openai.com/gptbot.json 的段清单核对。只有令牌命中、IP 没命中,那是另一个抄了名字的请求。
Googlebot 的验证和别人不一样吗?
不一样,而且更严。Google 不先让你去匹配静态清单,它要你先反查,确认域名结尾是 googlebot.com、google.com 或 googleusercontent.com,再正查一次、看是否回到原来那个 IP。它也提供 JSON 段清单,你要是更想直接比对地址也可以。
GPTBot 和 OAI-SearchBot 有什么区别?
两个令牌、两件事。OpenAI 文档说 OAI-SearchBot 是用来「surface websites in search results in ChatGPT's search features」的那一个,GPTBot 是抓「content that may be used in training」的那一个。放行一个、挡掉另一个是官方支持的配置,不是自相矛盾。
要回答「AI 爬虫来没来」,日志得留多久?
至少要覆盖一个完整的抓取周期,而这取决于你的站,我们给不出一个对所有站都成立的数字。稳妥的默认值是三十天。如果你只有七天,报数时就说清楚只有七天——短窗口只会少算,不会多算。
最后把边界说清楚:日志能证明抓取发生过,证明不了被使用、被排名或被引用,再多的计数也补不上这一步。它真正的作用,是把「AI 爬虫到底有没有来」从一个猜测,换成一份带日期的记录——而后面所有决定都建立在这份记录上。等你准备把这份记录变成一次改动、并且真的发上线,那正是 QueryWin 在做的事。
本文属于 QueryWin 实操手册 · 第 2 阶


