蜘蛛池知识

蜘蛛池入口頁的 JS 渲染與跳轉:内容藏在脚本里,蜘蛛能讀到多少

不少入口頁把跳轉和正文都交给 JavaScript,日誌里蜘蛛明明来過,目标頁却始终没被讀到。這篇梳理搜尋引擎抓取頁面时 HTML 获取與渲染两個阶段的關系,拆開纯 JS 跳轉、脚本注入内容、懒加载三種常见用法的風險,並给出用訪問日誌和無 JS 抓取對比来驗證蜘蛛實际讀到什么的做法。

蜘蛛池知识

蜘蛛池入口頁的 JS 渲染與跳轉:内容藏在脚本里,蜘蛛能讀到多少

做入口頁的人常有一個错觉:浏览器里打開一切正常,蜘蛛看到的應该也一样。但搜尋引擎抓取頁面通常分两步走——先按原始 HTML 拿一遍,再排队用渲染服務执行頁面里的 JavaScript。两步之間有時間差,能力也不完全對等。如果入口頁的關键内容或跳轉全靠脚本,蜘蛛可能只拿到一個空壳。

蜘蛛讀頁面,往往要分两次

第一次抓取拿到的是服務器返回的原始 HTML。這时候由 JS 動態寫入的文本、連結和跳轉指令都還不存在。搜尋引擎随後會把這些 URL 放進渲染队列,用無头浏览器再跑一遍,才可能看到脚本生成的内容。

渲染队列是有成本和延迟的:站点權重低、頁面重复度高、入口頁數量庞大的时候,很多 URL 可能等不到渲染那一步,或者渲染出来的结果和第一次抓取對不上。蜘蛛池入口頁往往數量多、结构相似,正好属于渲染资源容易被压缩的類型。

三種常见 JS 用法,風險不一样

纯 JS 跳轉

用 window.location 之類的方式把訪客带向目标頁,是入口頁最常见的做法。問题在于:這條跳轉指令寫在脚本里,第一次抓取拿到的 HTML 中並没有對應的連結,蜘蛛既看不到目标 URL,也判断不出這一步跳轉的含义,它大概率把入口頁当场處理完,不會跟進。

相比之下,服務端返回的 301 或 302,以及寫在 HTML 里的 meta refresh 再加一個普通 a 标簽連結,至少在原始 HTML 层面是可讀的。

内容靠脚本注入

有些入口頁把正文、内鏈、分頁都交给前端框架渲染。如果服務端不做预渲染,原始 HTML 里只剩一個空容器和几個 script 标簽。這種做法對入口頁尤其不划算——入口頁本身承担的就是让蜘蛛看到連結和上下文的功能,内容後置等于把最關键的部分藏起来。

懒加载與無限滚動

图片懒加载影响相對小,因為蜘蛛主要關心連結和文本。但列表、内鏈如果也做懒加载,或者靠滚動才触發加载,情况就不同了:蜘蛛不會主動滚動頁面,滚動区之後的内容和連結通常拿不到。

怎么確認蜘蛛到底讀到了什么

  • 看日誌里的资源請求。真實的渲染抓取通常會伴随一批 CSS、JS、图片請求,並且 UA 與主文档抓取一致。如果某個入口頁只有一次 HTML 請求、之後再無動静,大概率没有被渲染。
  • 對比有 JS 和無 JS 的结果。關掉 JS 打開入口頁,看還剩多少正文和連結。如果几乎為空,就要假设蜘蛛第一次抓取时同样是空的。
  • 看原始响應而不是最终 DOM。直接看服務器返回的 HTML 源碼,而不是浏览器開發者工具里渲染完的頁面结构,两者的差別往往比想象中大。
  • 观察内鏈的後續抓取。入口頁上指向目标頁的連結如果長期没有對應的訪問记錄,說明蜘蛛根本没讀到那些連結。

几條實務上的取舍

  1. 能放在原始 HTML 里的,就別放到脚本里。跳轉、正文主干、指向目标頁的連結,優先由服務端輸出。
  2. 必须依赖 JS 渲染时,考虑做服務端渲染或预渲染,保證第一次抓取就有可讀内容。
  3. 跳轉尽量用服務器端狀態碼,或 meta refresh 配合可见連結,不要只留一行 location 赋值。
  4. 入口頁的列表和分頁避免無限滚動,改成可点击的分頁連結。
  5. 上线一批入口頁後,隔几天翻一次日誌,確認蜘蛛是否只停留在 HTML 那一层。
渲染是搜尋引擎額外付出的成本,不是入口頁的預設待遇。把關键信息放在第一次抓取就能讀到的地方,才不用去赌渲染队列什么时候轮到自己。

需要說明的是,即使原始 HTML 完全可讀,也不代表蜘蛛一定會跟進每一條連結、一定會抓取目标頁——抓取预算、頁面质量、重复度都會影响结果。JS 這一层只是最容易排查、也最容易改掉的一個問题。