搜尋抓取

服務端 HTML 與渲染後 DOM:搜尋蜘蛛在哪一层看到 URL

很多站点把詳情連結交给前端脚本生成,URL 只存在于渲染後的 DOM 里,發現渠道随之收窄。本文拆開抓取鏈路上的原始响應與渲染两個阶段,說明哪些寫法會让連結延後出現,给出禁用 JS 對比、源碼检索等自查步骤,以及把關键入口放回服務端 HTML 的几種做法。

搜尋抓取

服務端 HTML 與渲染後 DOM:搜尋蜘蛛在哪一层看到 URL

抓取一個 URL 时,搜尋蜘蛛通常先拿到服務端直接返回的响應:狀態碼、响應头和 HTML 源碼。渲染(执行 JS 得到 DOM)是之後的事,是否發生、何时發生並不完全由站点决定。理解這两級差异,能解释不少“頁面明明有連結,却没被發現”的情况。

抓取鏈路上的两個阶段

第一阶段是原始响應。Sitemap 里的地址、HTML 里的 a href、日誌中能看到的那次請求,大多在這一层完成。第二阶段是渲染:脚本执行、接口返回、节点插入,最後得到用戶看到的 DOM。渲染资源是有限的,站点規模越大,落到單個 URL 上的渲染次數越少。

两個阶段對 URL 發現的意义並不相同:第一阶段决定“這個地址能不能被發現”,第二阶段更多决定“内容能不能被完整理解”。把關键入口只放在第二阶段,等于把發現權交给一個並不确定的环节。

哪些寫法會让 URL 只出現在渲染後

  • 前端路由:列表和詳情地址由 JS 生成,源碼里只有空容器。
  • 懒加载與無限滚動:滚動或点击後才請求下一批資料,地址藏在接口响應里。
  • 接口拼装:模板由 fetch 回来的 JSON 渲染,連結文本和 href 都来自資料。
  • 按钮跳轉:点击後执行脚本跳轉,源碼里没有可跟随的連結。

這些做法本身不會必然導致不抓取。真實情况是發現渠道從“内鏈”收窄到“Sitemap 與接口地址”,一旦 Sitemap 没覆盖到,這批 URL 就只能等外部連結或推送带進来,节奏明顯變慢。

自查:確認 URL 在哪一层可见

  1. 用 curl 或查看網頁源代碼,直接搜尋目标詳情 URL 是否出現在原始 HTML 中。
  2. 以禁用 JS 的方式抓取同一列表頁,統計可發現的連結數量,與浏览器中看到的作對比。
  3. 對比“查看網頁源代碼”和開發者工具 Elements 面板里的連結數,差值就是渲染层新增的部分。
  4. 在日誌里观察渲染請求與普通抓取請求的分布,看哪些栏目几乎只有渲染訪問。
  5. 抽一個詳情頁,確認它的入口究竟是 Sitemap、内鏈,還是只存在于某個接口响應中。

做完這几步,通常能得到一張清晰的图:哪些栏目的入口是稳的,哪些完全依赖渲染或推送。

把關键入口放回原始 HTML

  • 列表頁尽量服務端渲染,至少保證首屏的詳情連結以真實 a href 出現在源碼里。
  • 分頁、翻頁、下一頁使用可跟随的連結,而不是纯 JS 事件。
  • 懒加载保留前若干條為静態連結,其余再交给脚本补充。
  • 客戶端路由的站点,對重点栏目做预渲染或静態化輸出。
  • 無论采用哪種方案,Sitemap 都要覆盖全部詳情地址,作為發現渠道的兜底。
渲染抓取是补充手段,不是内鏈的替代品。能放在原始 HTML 里的入口,尽量不要只留在脚本执行之後。

核對时容易忽略的点

一是缓存差异:CDN 或頁面缓存返回的 HTML 可能與渲染服務看到的版本不同,核對时要確認請求命中的是哪一份。二是接口權限:抓取侧没有登入態,接口返回空數组,渲染出来的 DOM 自然也没有連結。三是移動與桌面模板不同,入口數量可能不一致,需要分別检查。四是改了前端框架後,舊的内鏈可能整体消失,而日誌里的抓取趋势變化往往滞後几周才明顯。

把這些点按栏目记錄一次,後續每次改版前後對比連結數量,URL 發現的稳定性會比依赖人工抽查靠谱得多。