Skip to content
Published on

访客统计里只看得见 0.5% 的流量 —— 防机器人要看来源,而不是自我声明

分享
Authors

引言 —— 仪表盘上看不见的那 99%

2026 年 8 月 7 日,一个叫 PatronView 的站点的运营者公开了一整年抵御爬虫的记录。这是一个美国慈善捐赠者数据库,基于 IRS 990 申报表和公开的捐赠者名单,做出了 150 万个个人档案页面。

文章公开的那一周,服务器从外部收到了 250 万次请求,完整送出了 128 万个页面。可访客统计里只记录了 5,977 次页面浏览。

也就是说,每有一次看得见的页面加载,就有大约 214 次看不见的。

这里要学的不是「机器人很多」这件事。机器人很多,大家都知道。要学的是:你现在盯着的那个指标,在结构上根本没法把这个局面呈现出来。

JavaScript 分析工具数不到机器人

原因很简单。包括 Plausible、Fathom、Google Analytics 在内,客户端分析工具只统计会执行 JavaScript 的访客。而大多数机器人不执行 JavaScript。

于是仪表盘展示的是一个每天 500 人左右的小巧站点,服务器却每周应答着数百万次请求。两个数字都是真的。它们只是在数不同的东西。

实务上的结论只有一条。判断机器人流量时,要看服务器日志或边缘日志,而不是分析工具。 并且要定期核对这两者之间的差距。差距开始拉大的那个时点,就是有什么事情开始了的时点。

原文里第一次发现机器人,走的正是这个路子。2025 年 11 月,连续几天出现了 4,000 名「访客」。每一个都恰好只看一个页面,跳出率 99%,没有来源页。而且他们只扫一种特定类型的页面 —— 真实访客里只有 10% 会看的那种。

这些信号中任何单独一个都不算决定性,但凑在一起就很明确了。而且这些信号在分析工具里也能看到,因为那是一批会执行 JavaScript 的机器人。

每次抓取带来多少访客 —— 把判断压缩成一个数字

原文里最实用的部分,是作者最后落定的那个指标。爬虫每读走多少个页面,才给你送来一个访客。

作者测到的值是这样的。

爬虫每送来 1 名访客所抓取的页面数
Googlebot46 比 1
Bingbot406 比 1
Claude-SearchBot35,000 比 1
Amzn-SearchBot未带来访客

Claude 这一侧的依据很具体。某一周里 Claude-SearchBot 请求了 420,680 个页面,而同一周通过 Claude-User 这个真人请求页面时才会使用的另一个 User-Agent 进来的访客,是 12 位。换算成带宽,给机器人的是 4.63GB,给那个机器人送来的人的是 175KB。

Amazon 这一侧是每天约 117,000 次,是那个时点的头号爬虫,而它一个访客都没送来。

这个指标的好处在于,它把政策判断从道德变成了算术。不是「AI 爬虫很坏」,而是「这个爬虫在用我的带宽,却什么都不还回来」。作者写道,Bingbot 的 406 比 1 比 Google 差九倍,但带来的访客确实在增长,所以继续放行。用同一套标准却得出不同结论,恰恰是好标准的证据。

拦截之后的观察也值得记下来。在防火墙上挡住 Claude-SearchBot 之后,原本每天 6 万次的请求掉到了每天 25 次左右的尝试。用作者的话说,「守规矩的 AI 公司真的会接受 403」。

公开的比率和自己站点的比率为什么不一样

作者一边引用「Cloudflare 说 Anthropic 的爬虫大约每 3,000 次抓取带来 1 名访客」,一边写下自己站点上测到的是 35,000 比 1。

搞清楚这两个数字为什么不同,很重要。

Cloudflare 首次公开这个指标的文章发表于 2025 年 7 月 1 日,并明确写出了计算方式:把来自与该平台相关联的 User-Agent、且响应内容类型为 HTML 的请求总数,除以来自该平台的引流流量。当时在 2025 年 6 月 19 日至 26 日这个区间里,Anthropic 被报告为 70,900 比 1。

同一篇文章里还有 Cloudflare 自己加的一句限定。Claude 原生应用送出的引流流量不带来源页头部,而且其他原生应用很可能也一样。所以他们写道,自己的计算「可能高估了这个比率,而高估到什么程度并不清楚」。

由此可以推出三点。

第一,这个比率会随时点大幅变动。70,900、3,000、35,000 全都是不同时点、不同总体上的值。把其中任何一个引用为「AI 爬虫的比率」,都是错的。

第二,自己站点的值比汇总值更重要。它会随你的内容性质、读者的地理分布、索引状况而大幅变化。

第三,没有来源页头部的引流会被少算。也就是说,真实的比率可能比测到的更有利。在做出拦截决定之前,你必须知道这个局限。

相信自我声明的规则,和看来源的规则

原文的附录里完整公开了实际的防火墙规则表达式。比每一条规则本身更重要的,是它依赖的是什么性质的信息

有些规则依赖自我声明的值。User-Agent 字符串就是典型。

(lower(http.user_agent) contains "semrushbot") or
(lower(http.user_agent) contains "ahrefsbot") or
(lower(http.user_agent) contains "mj12bot")

这类规则只对诚实的爬虫有效。作者也写道,那些 SEO 爬虫会诚实地表明自己的身份,这值得感谢。而对撒谎的一方,它毫无作用。

依赖来源信息的规则则不同。IP 来自哪个国家、属于哪个 ASN,不是发请求的一方可以随便决定的。

((ip.src.asnum in {212238 139341 9009}) or
 (ip.src.continent in {"AF" "AN" "AS" "OC" "SA" "T1" "EU"}))
and not cf.client.bot
and not (ip.src.country in {"GU" "AS" "MP"})

作者撑得最久的两条规则都属于这一类。对北美以外的大洲下发挑战,对 46 个大型云厂商 ASN 下发挑战。因为真实读者有 97% 在北美,而人不会从 AWS us-east-1 的 IP 上浏览网页。之所以是挑战而不是拦截,是因为里面可能有在用云桌面或 VPN 的人。

第三类是密码学验证。Cloudflare 会验证 Googlebot、Bingbot、Applebot 的身份,规则里用 cf.client.bot 引用。作者点出的顺序才是诀窍。把这条绕行规则放在拦截规则之后,你决定要挡的那些经过验证的机器人依然被挡着,而挑战绝不会发到 Google 头上。

设计规则时,永远先问这个问题。这条规则引用的值,对方能不能随意改动。 如果能改,那么这条规则的寿命,就到对方开始在意的那一天为止。

面对住宅 IP 僵尸网络,来源规则也会失效

不过基于来源的规则也有极限,而原文正正撞上了这个极限。

2026 年 7 月,新的一波来自美国。来自俄亥俄州的一户人家,走的是 Spectrum 的线路。大洲规则放行,数据中心规则也放行。两条规则都会把这些流量直接送进来。7 月 31 日当天的独立 IP 涨到了 124,000 个,而平时的基线约为 18,000 个。

按住宅代理网络的定义,本来就会这样。它按请求为单位租用成千上万条真实家庭宽带线路,所以每一个请求都来自真人的线路。作者的结论很准确:在网络层挡住它们,在设计上就是不可能的。

针对这一波,作者找到的应对落在另一个轴上。同一批僵尸网络在假装自己是 Chrome 118 到 120。等于说 2023 年的浏览器版本被原封不动地固化在了爬虫工具包里。

于是对老浏览器下发挑战。Chrome 100 到 130,以及老版本的 Firefox。作者先核对了真实流量:真正从搜索进来的访客里,使用这么老的浏览器的比例是 0.54%,其中大部分是 Firefox 115 ESR,所以单把它排除在外。

这条规则最终依然依赖自我声明的值,也就是 User-Agent。对方只要改一个字符串它就失效了。作者自己也清楚这一点,把它称作「我喜欢的那条蠢规则」。要点在于:如果你要用依赖自我声明的规则,先测出这条规则会打到多少比例的真实用户,然后再用。

去量一量防御装置本身的成本

这篇文章里最出人意料、也最具普适性的教训在这里。

Cloudflare 的「JavaScript Detections」功能整整一年都在往每一个页面里注入验证脚本。作者是在想给站点提速的时候发现它的。

那段脚本在一台中端手机上消耗了 2,875 毫秒。而站点自身的全部 JavaScript 是 278 毫秒。这是移动端 Lighthouse 分数只有 58 分的最大原因,更要命的是,在所使用的套餐里,那个判定结果甚至没法在防火墙规则中读取。等于为了一份谁也读不到的遥测数据,付出了 40 分的性能。

8 月 5 日把这个功能关掉之后,一小时之内 Lighthouse 分数就变成了 99。

而五个小时后,Azure 上的一个爬虫在一小时内取走了 23,000 个页面。它动用了 80 多个 IP,每一个都老老实实待在速率限制之下。也就是说,那个功能确实在干活。

这个故事的教训既不是「别关」,也不是「快开」。而是:你有没有量过防御装置的成本。 机器人对抗功能通常以一个「开启」开关的形式提供,一旦打开就再也没人回头看。而在这期间,那个功能会持续从你的性能预算和用户体验里收费。

如何把它运营得可测量,原文里也有诀窍。用挑战代替拦截,你就还剩下一个通过率。在作者的 48 小时区间里,106,437 次挑战中有 252 次通过,通过率 0.24%。作者的判断标准很清楚:通过率 0.2% 说明是机器人,那就保留规则;通过率 30% 说明你在向人收税,那就改规则。

工作量证明解决了什么,又没解决什么

这篇文章在 Hacker News 上的讨论里,密度最高的争论是关于 Anubis 这类工作量证明方案的。两边的说法都值得原样搬过来。

批评一方是这样说的。Anubis 的挑战形式是在挑战字符串后面附加一个 nonce 再求 SHA-256 哈希,但由于 nonce 放在后面,前半部分的压缩轮次是可以缓存的。比特币挖矿里那套中间状态复用的技巧原样适用。批评者指出,把 nonce 放在前面本可以避免这个问题。因此原生代码求解器比浏览器 JavaScript 快上数千倍,浏览器里要跑十分钟的难度,它以毫秒级就解掉了。

辩护一方的反驳则是经验性的。可以被绕过和实际被绕过是两回事。专门定制的爬虫确实能绕得高效得多,但几乎没有人这么做。因为绝大多数机器人并不是冲着你来的,它们只是想以低成本大量收集。

Anubis 的维护者也参与了讨论,表示下个版本之后正在准备 WASM 求解器功能,而要一路验证到老式智能电视的浏览器很花时间。

归纳起来,工作量证明不是区分人与机器人的装置,而是抬高大量收集单价的装置。这样理解之后,评价标准也就清楚了。对把你当作目标的对手它作用不大,对无差别的大规模收集则相当有效。而且因为它强制执行 JavaScript,对文本浏览器用户和慢速线路用户来说是实打实的成本。

作者本人的结论也不是技术性的,而是经济性的。爬取之所以持续恶化,是因为它持续变便宜,而真正的解法是一个市场 —— 比如按次抓取计费。在那个市场出现之前,作者的规则只有一句话:一个访客都不送来的爬虫,就挡掉。

参考资料

本文的数值来自单独一个站点的实测,会随站点性质与读者构成大幅变化。这些都不是我亲自复现出来的值。