搜尋抓取

JS 渲染出来的連結:蜘蛛什么时候才看得到

前端渲染的頁面里,連結常常藏在 JS 中,蜘蛛第一次抓取时可能什么也看不到。本文說明第一次抓取與渲染环节的差別、哪些 URL 最容易在中間掉队,以及把關键連結放回 HTML、用日誌驗證抓取效果的具体做法。

搜尋抓取

JS 渲染出来的連結:蜘蛛什么时候才看得到

現在不少站点的主体内容和連結靠前端框架渲染,服務器返回的原始 HTML 里只有一段脚本和一個空的容器。對用戶来说看不出区別,但對搜尋蜘蛛来说,第一次拿到的頁面和你在浏览器里看到的内容,可能是两回事。這篇文章说说這種頁面里,蜘蛛怎么發現 URL、什么时候才看得到連結,以及站点侧能做点什么。

第一次抓取:蜘蛛拿到的是原始 HTML

蜘蛛請求一個 URL 时,預設先取服務器直接返回的 HTML 响應。此时脚本還没有执行,動態内容、异步加载的列表、点击後才生成的連結,都還不存在。如果導航、列表、分頁、詳情連結全部由 JS 生成,那么這一次抓取里,蜘蛛能看到的 URL 數量可能接近于零。

這不代表這些 URL 永遠不會被抓,只是它們要等到渲染环节才有机會被發現。而這個环节是有額外成本的:需要排队、需要资源、可能失敗,也可能只對一部分頁面执行。

渲染环节:連結被發現的時間被推後

搜尋引擎會有一套渲染机制,把頁面放進近似浏览器的环境里执行脚本,等 DOM 稳定後再提取内容和連結。這個過程會碰上几個現實問题:

  • 排队:渲染比直接讀 HTML 慢得多,通常只有部分頁面會進入渲染,站点侧無法精确控制。
  • 超时:脚本里有長時間轮询、阻塞的第三方請求或报错中断,渲染可能在連結出現之前就結束。
  • 接口依赖:内容来自接口,抓取时接口被限流或返回错誤,渲染出来的頁面就是空的。
  • 二次發現:渲染後才出現的 URL 等于多了一道工序,進入抓取队列的時間明顯晚于 HTML 里原本就有的連結。

哪些 URL 最容易在這個环节掉队

  • 只有 JS 才會生成的列表頁、分頁連結和篩選入口。
  • 核心導航放在脚本里,HTML 中没有任何可点連結。
  • 詳情連結靠点击事件跳轉,没有真正的 a 标簽。
  • 图片、样式等资源路径由脚本拼装,HTML 里看不到。

這些内容不一定抓不到,但發現路径更脆弱,在日誌里出現的频率通常也更低。

让關键 URL 在第一次抓取里就可讀

比較稳妥的思路是把「發現」和「体驗」分開處理:重要的、需要被蜘蛛尽快知道的 URL,尽量放在服務器返回的 HTML 里,样式和交互再交给前端。

  1. 導航和列表用普通 a 标簽輸出,href 指向真實 URL,不要用 javascript:void(0) 或纯点击事件。
  2. 分頁在 HTML 里给出可点的上一頁、下一頁連結,而不是滚動到底再异步加载。
  3. Sitemap 只放需要被抓的規范 URL,作為内鏈的补充,而不是唯一入口。
  4. 關键頁面尽量避免依赖第三方脚本才能顯示出内容和連結。
  5. 渲染失敗时退回可讀的静態内容,至少让 URL 结构能被讀到。

怎么驗證蜘蛛到底看到了什么

最直接的驗證方式是看服務器日誌:把真實搜尋蜘蛛的 UA 與 IP 核對之後,观察它請求某個頁面时,日誌里紧随其後是否出現了頁面内其它 URL 的請求。如果没有,說明那些連結在這次抓取里没被讀到。也可以直接關閉 JS 抓一份 HTML,對比里面還剩多少可点的連結,這份 HTML 大致就是蜘蛛第一眼看到的版本。

小结:URL 發現越依赖前端渲染,鏈路越長、越不可控。把重要的連結和内容放進服務器直接返回的 HTML,是成本較低、也更容易長期保持稳定的做法。