網站收錄

首屏内容由 JS 渲染:抓取到的 HTML、渲染结果與收錄之間的關系

前端渲染的站点里,搜尋引擎第一次請求拿到的原始 HTML 往往只是一個空壳,正文、内鏈和元信息都要等 JS 执行後才出現。這篇文章梳理抓取、渲染與收錄之間的先後關系,列出容易出現問题的頁面類型,並给出一套可以照着做的自查步骤。

網站收錄

首屏内容由 JS 渲染:抓取到的 HTML、渲染结果與收錄之間的關系

現在很多站点用前端框架渲染,頁面里能看到的正文、列表、價格,全部由 JavaScript 在浏览器中生成。對用戶来说没有問题,但對搜尋引擎来说,第一眼拿到的和最终看到的可能不是同一份東西。這中間的差距,常常就是“抓取看起来正常、收錄却不動”的原因之一。

抓取到的 HTML 和渲染後的頁面,是两份東西

搜尋引擎抓取一個 URL 时,第一步通常是直接請求這個地址,拿到服務器返回的原始 HTML。這份 HTML 里如果只有一個空壳容器和几個 script 标簽,爬虫第一時間並不能看到正文。之後,搜尋引擎可能會把這個頁面放進渲染队列,用接近浏览器的环境执行 JS,再拿到渲染後的结果。

問题在于渲染是有成本的。它比直接讀 HTML 慢得多,也更占资源,而且不是每個 URL 都會被渲染,也不是每次抓取都會渲染。所以有的頁面最终被正确理解,有的頁面則在“只拿到空壳”的狀態下就被處理掉了。

哪些情况最容易出問题

  • 正文、商品信息、文章列表完全靠 JS 請求接口後再插入。
  • 關键内鏈寫在 JS 里,原始 HTML 中没有任何 a 标簽。
  • 标题、canonical、meta robots 由前端動態寫入。
  • 内容要等用戶交互,比如点击、滚動、切換标簽頁之後才出現。
  • 接口返回依赖登入態或特定 Cookie,爬虫拿不到資料。

這些情况不一定都會導致不收錄,但會明顯增加不确定性。尤其是内鏈:如果連結只存在于渲染结果里,URL 發現這一步就會變慢,新頁面可能很久都進不了抓取队列。

服務端渲染與预渲染是常见折中

要减少這類不确定性,常见的做法是让服務器直接返回带内容的 HTML。可以是服務端渲染,也可以是构建时预渲染,或者對爬虫做静態化。目标只有一個:让第一次請求就返回正文和主要連結,而不是等到 JS 执行完才出現。

需要注意的是,服務端返回的内容和渲染後的内容要尽量一致,至少标题、正文主体、canonical 與 robots 元信息不要互相矛盾。如果两份内容差异過大,反而會让搜尋引擎难以判断哪個才是頁面的真實版本。

几個容易忽略的细节

分頁與懒加载。無限滚動、点“加载更多”才出現的内容,通常不會被当作頁面的一部分来處理。如果這些内容有獨立地址,最好给每個地址一個可以直接訪問的 URL。

接口稳定性。渲染时調用的接口如果超时或返回错誤,渲染结果就是残缺的。這類失敗往往不會体現在常規的可用性监控里,需要單獨观察。

別用 JS 寫關键指令。noindex、canonical、hreflang 這類元信息,尽量在服務端輸出的 HTML 里就寫清楚,避免依赖前端注入。

渲染成本要花在值得的頁面上。如果一個頁面内容本身就很少,或者本来就不需要被收錄,没必要為它增加渲染负担。

怎么自查

  1. 用浏览器的“查看網頁源代碼”(不是审查元素)看原始 HTML,確認正文和主要連結是否在里面。
  2. 用抓取工具的模拟抓取與渲染功能,對比渲染前後 HTML 的差异。
  3. 關閉浏览器 JS 後打開頁面,看還剩多少内容,這是一種粗糙但直观的參照。
  4. 在服務器日誌里观察目标 URL 是否被反复抓取却没有進入索引。
  5. 用網址检查類工具看抓取版本與渲染版本是否一致。
抓取成功不等于内容被理解,内容被理解也不等于一定會被收錄。渲染只是這條鏈路上的一個环节,把它梳理清楚,比猜测算法更實际。

最後回到收錄本身:JS 渲染影响的主要是“搜尋引擎能看到什么”,而不是“搜尋引擎愿不愿意收錄”。把内容尽早、完整、稳定地交到爬虫手里,剩下的判断交给頁面质量本身。如果你的頁面在抓取日誌里表現正常但長期不進索引,值得先检查一下原始 HTML 里到底有没有東西。