用戶打開的頁面是浏览器执行完脚本之後的样子,蜘蛛拿到的却是服務器先返回的那份 HTML。抓取和渲染通常是两個环节:先把原始响應抓回去,再排队進入渲染。两個环节之間可能隔几秒、几分钟,站点越大、待渲染的頁面越多,這個間隔越容易被放大。
如果頁面的正文和連結主要由 JavaScript 生成,第一遍抓取看到的就只是一個空壳。空壳本身不一定是错誤,但它让這次抓取拿不到可用的内容,也找不到頁面里指向其他 URL 的路径。
不执行脚本时,蜘蛛還能讀到什么
在只拿到原始响應的情况下,下面這些内容通常是可以被讀到的:
- HTML 源碼里的标题、正文段落、图片 alt 文本
- 寫在 a 标簽 href 属性里的連結,而不是 onclick 或 JS 跳轉
- meta 信息、canonical、robots 指令
- 响應头里的狀態碼、Content-Type 與字符集
而下面這些,在抓取阶段往往讀不到:前端框架渲染出来的正文、骨架屏占位块、点击按钮触發的路由跳轉、用 CSS 或伪元素插入的文字。
空壳 HTML 會带来哪些连鎖反應
第一遍抓不到内容,影响的並不只是這一頁:
- 頁面里的内鏈没被抓到,那些 URL 就少了一條被發現的通路;
- 蜘蛛無法從正文判断頁面主题,連結周邊的语境也跟着變弱;
- 如果渲染环节因為超时、脚本报错或接口被拦而失敗,頁面可能長期停留在“已發現、未抓取”的狀態。
這並不等于 JS 渲染的頁面一定抓不到,而是说它多了一层不确定性,而這层不确定性通常不在站長手里。
把關键内容放回原始响應
比較稳妥的思路是让第一遍抓取就有東西可讀:
- 标题、主体内容、面包屑和主要内鏈用服務端渲染或预渲染輸出,交互部分再交给前端;
- 頁面之間的跳轉使用标准 a 标簽和 href,不要用 onclick 或脚本跳轉代替;
- 列表頁、詳情頁的連結保持静態可点,不要把 URL 只寫進 JS 變量;
- 避免 hash 路由,蜘蛛通常不會把井号後面的路径当作獨立 URL;
- Sitemap 里保留這些 URL,作為内鏈之外的补充發現通道。
怎么確認第一遍抓到了什么
最直接的办法是關掉 JavaScript,或者用命令行工具拉一次原始响應,看看返回的 HTML 里有没有正文和連結。也可以對照服務器訪問日誌,確認蜘蛛的請求确實落在頁面 URL 上,而不是只請求了一堆接口。搜尋引擎提供的網址检查工具可以看到渲染前後的差异,适合用来做對照。
如果正文和連結必须靠脚本才能出現,至少保證首頁、分類頁和主要入口頁是静態可讀的,让蜘蛛有路可走。
小结
JS 渲染不是不能做,而是要清楚蜘蛛的第一眼和用戶看到的可能完全不同。把标题、正文和内鏈尽量往前放,减少對渲染环境的依赖,URL 被發現和被理解的机會才更稳。