AI 爬虫会执行 JavaScript 吗:先查它实际收到了什么
AI 爬虫会执行 JavaScript 吗?多数不会,所以页面能返回 200 却什么都没说。一条命令看爬虫实际拿到的内容,加三种修法和各自代价。

AI 爬虫会执行 JavaScript 吗?多数不会——而这正是「返回 200」和「说了点什么」之间的区别。搜索引擎会按自己的排期去渲染,而喂答案引擎的那批 AI 爬虫,基本上是拿到什么 HTML 就读什么。你的正文如果是脚本加上去的,爬虫收到的是一个空壳,然后它就走了,而且任何地方都不会报错告诉你。
读这篇之前
这一章在怎么查网站能不能被 AI 抓取的下面一层。那一步问的是字节回不回得来,这一步问的是回来的字节里有没有你的内容——同一个状态码,两个完全不同的问题。
为什么 200 也可能是一张空页
浏览器的流程是:下载 HTML、执行 JavaScript、再去取数据、最后把文字画出来。一个不执行脚本的爬虫,停在第一步。服务器发出去的那份就是它拿到的全部——而在一个前端渲染的站上,那份东西是一具只有标签、没有内容的壳。
查这件事最不该用的工具就是你的浏览器,因为它恰恰是唯一保证会把空缺补上的那个客户端。
AI 爬虫会执行 JavaScript 吗:先查它实际收到了什么
用爬虫的身份取一次页面,把脚本和标签剥掉,数剩下多少。一个你知道很长的页面,如果这个数很小,说明内容不在 HTML 里。
URL="https://example.com/"
curl -s -A "Mozilla/5.0 (compatible; OAI-SearchBot/1.4; +https://openai.com/searchbot)" "$URL" \
| python3 -c "
import sys, re, html
raw = sys.stdin.read()
body = re.sub(r'(?is)<script.*?</script>', '', raw)
body = re.sub(r'(?is)<style.*?</style>', '', body)
txt = html.unescape(re.sub(r'<[^>]+>', ' ', body))
txt = re.sub(r'\s+', ' ', txt).strip()
print('原始字节 ', len(raw))
print('可读正文 ', len(txt))
print('有没有 h1 ', bool(re.search(r'(?i)<h1[\s>]', raw)))
print(txt[:300])
"
最后一行打出来的,是爬虫能读到的开头。如果那是一段 cookie 提示、一个导航菜单、或者干脆什么都没有,问题就找到了。
内页也要查,不只是首页
至少测三个网址,因为同一个站内部经常不一样。首页往往是手工搭的、服务端渲染的,而真正的内容跑在一个不是这么回事的应用里。首页、一篇文章或产品页、一个藏在筛选或标签页后面的页面,各测一个。
最常见的形态是首页过、文章模板不过,而这是最糟糕的一种组合:你去查的那一页看起来没问题,你真正想被引用的每一页都是空的。只测一个网址就宣布网站健康,是这个检查最常见的误用方式。
for u in \
"https://example.com/" \
"https://example.com/blog/some-article" \
"https://example.com/products?filter=new"
do
n=$(curl -s -A "Mozilla/5.0 (compatible; OAI-SearchBot/1.4; +https://openai.com/searchbot)" "$u" \
| sed -e 's/<[^>]*>/ /g' | tr -s ' \n' ' ' | wc -c)
printf '%-52s %s\n' "$u" "$n"
done
这个更糙的一行版没有剥脚本,所以数字偏大——它是用来在同一个站内部横向比较的,不是用来做绝对判断的。
这个数怎么读
没有通用阈值,所以拿页面自己比,别拿别人的基准比。一篇两千词的文章,可读正文应该在几千字符这个量级。
| 你看到的 | 怎么读 |
|---|---|
| 可读正文大致等于肉眼看到的文章 | 没问题。服务端渲染或者预渲染。 |
| 只有几百字符,而且全是导航和页脚 | 前端渲染。爬虫看不到任何有价值的东西。 |
| 原始字节很大,可读正文很小 | 发出去的是脚本和数据,不是内容。 |
根本没有 h1 | 脚本跑起来之前,这份文档连标题都没有。 |
三种修法,各自的代价
按代价从低到高排。多数站只需要第一种,而且动手重建之前值得先确认自己到底是哪一种。
| 修法 | 适合 | 代价 |
|---|---|---|
| 构建时预渲染 | 不常变的内容:文章、文档、营销页 | 最低。通常改一个框架配置。 |
| 每次请求服务端渲染 | 个性化或者一直在变的内容 | 中等。是真的基础设施工作。 |
| 关键内容随首屏 HTML 一起发,其余再水合 | 只有一部分是内容的应用 | 对应用改动最小,但要刻意划分。 |
🚫 不在这张表上的是「给爬虫发一份跟人不一样的 HTML」。那是另一个风险大得多的决定,而且它不是这个问题的解法。
确认修完真的生效了
改完渲染方式,把最早那条命令再跑一次,跟你记下来的数字比。这一步比听上去重要,因为号称会预渲染的构建设置,有时只预渲染了你列进去的那些路由,而你在意的那一个正好没在列表里。
真正修好的时候,三件事会一起变:可读字符数涨到大致等于肉眼看到的文章、交付的 HTML 里出现了 h1、抽出来的正文开头是你真正的第一段而不是导航菜单。如果字符数涨了、开头却还是导航,说明内容在了但埋得深,被摘取时仍然会输给那些答案就在最前面的对手。
要在部署之后再测一遍,别拿预览环境测。预览环境的渲染行为经常和生产不同,而这个检查的全部意义就是看公开网址实际发出去什么。
那些确实会渲染的引擎呢
Google 会执行 JavaScript,但是排队的:抓取和渲染是两个阶段,中间的间隔可能拉得很长。所以一个前端渲染的页面对 Google 不是看不见,是慢;而对那些根本不渲染的爬虫,就是看不见。
这个分野正是这一章放在手册里、而不是放在一份通用 SEO 指南里的原因。如果消费方只有 Google,前端渲染是个性能问题。因为答案引擎取材的那批爬虫多数不渲染,它就变成了一个可见性问题,而代价恰好落在这本手册关心的那几个界面上。
三种常见的做错
三种都是用错了客户端,然后得出一个笃定的结论。
- 在浏览器里用「查看源代码」检查。有些浏览器给你看的是渲染后的 DOM 而不是服务器发来的文档,那会把整个问题藏起来。用
curl,不要用标签页。 - 以为 Google 会渲染就等于所有人都会渲染。Google 确实渲染,按它自己的排期。那说明不了喂答案引擎的那批爬虫,而这本手册讲的正是那批。
- 修完首页就收工。首页往往是全站最手工的一页。内页也要测,结果经常不一样。
常见问题
Google 到底渲不渲染 JavaScript
渲染,但渲染和抓取分开排队,可能滞后。对这一章有实际意义的一点是:Google 是这批客户端里能力最强的一个,所以在 Google 那儿过了,说明不了其他几家。
可读正文多少字符算安全
我们不给这个数字,因为它完全取决于这一页本来该有多长。真正有意义的对照是「读者看到的」和「取回来的」之间的差距——差距大本身就是结论,任何绝对值都不是。
我的框架说它是服务端渲染,还需要查吗
需要,而且大部分意外都出在这儿。号称服务端渲染的框架,照样可能发出空页面:某个组件在客户端才去取数据、某条路由退出了静态生成、某块内容被包在一个只在浏览器里挂载的东西里。配置说的是意图,抓一次说的是结果。
空壳对 Google 排名也有害吗
至少是延迟,因为渲染是后面才发生的第二轮。会不会影响排名,我们没有在自有站上测过,所以不下这个断言。
下一步
如果抓回来的确实是你的文章,这一层就通了,剩下的问题是内容说了什么,而不是它到不到得了。如果抓回来是个壳,先修这个再谈改写——后面每一章都默认爬虫读得到你正在编辑的那些字。
我们用同一条命令测了 15 个知名网站,可读正文从 342 到 25,082 字符,数字在AI 爬虫从前端渲染的网站上拿到了什么。把修法做完、发出去、再推送收录,才是大部分网站真正卡住的地方。
本文属于 QueryWin 实操手册 · 第 2 阶



