搜尋抓取

蜘蛛看到的是源碼還是渲染後的頁面:JS 站点的抓取鏈路與常见断点

蜘蛛處理一個 JS 頁面时,通常先拉取原始 HTML,再把依赖脚本的 URL 排進渲染队列。本文拆解這两次机會各自能拿到什么、在哪些环节容易断掉,以及如何用 URL 检查工具、服務器日誌和禁用 JS 的對照来確認蜘蛛實际看到的内容。

搜尋抓取

蜘蛛看到的是源碼還是渲染後的頁面:JS 站点的抓取鏈路與常见断点

越来越多站点把列表、詳情甚至整站導航交给 JavaScript 渲染。结果是在浏览器里一切正常,在蜘蛛那邊却只拿到一個空壳 HTML。要排查這類問题,先得理解一件事:搜尋蜘蛛處理一個 URL,往往不是一次抓取,而是两次。

第一次:拉取原始 HTML

蜘蛛首先請求服務器返回的源碼,也就是未执行脚本的那份 HTML。這個阶段它能讀到服務端輸出的标题、正文、連結、结构化資料和 meta 标簽。如果連結在源碼里就已经存在,蜘蛛可以直接顺着走;如果連結是脚本执行後才插入 DOM 的,第一次抓取时它看不到。

一個實用的判断标准是:關掉浏览器 JS,頁面還剩多少可讀内容和可点連結。剩下的那部分,就是蜘蛛在第一時間能拿到的東西。

第二次:進入渲染队列

對于確認依赖脚本的頁面,搜尋引擎會安排一次渲染,用無头浏览器执行 JS 並讀取渲染後的 DOM。這一步有几個特点:

  • 排队:渲染资源有限,通常是先發現、後渲染,存在延迟,也不是每個 URL 都能排上。
  • 超时:脚本执行、接口請求、图片與字体加载都有時間上限,超出的部分拿不到。
  • 不交互:不會点按钮、不會滚動到底、不會關閉彈窗、不會填表單。

換句话说,渲染阶段能救回一部分内容,但它不是保險,更像一次补考。

常见的抓取断点

1. 内容完全靠接口异步拉取

頁面源碼里只有容器和脚本,資料要等接口返回才出現。如果接口响應慢、需要特定請求头,或者對爬虫 UA 返回不同结果,渲染时同样可能拿不到東西。

2. 連結依赖点击或滚動

加载更多按钮、無限滚動、Tab 切換,都會让後續内容在渲染阶段也不出現在首屏。分頁入口如果只是脚本事件而不是真實連結,抓取路径就断在這里。

3. 懒加载與占位内容

图片、评论区等资源進入视口才加载,渲染器不一定滚動,于是這部分可能長期不參與抓取。

4. 登入、驗證碼與地区限制

被拦住的頁面在源碼阶段就可能拿到 403 或跳到登入頁,後續渲染更無從谈起。

5. 渲染脚本本身报错

JS 抛错、依赖的外鏈资源被墙、跨域請求被拒,都會让 DOM 停在半成品狀態。

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

  1. 用搜尋引擎提供的 URL 检查工具,對比原始 HTML 與渲染後 HTML 两種视图。
  2. 在服務器日誌里看该 URL 的抓取次數與狀態碼,渲染抓取有时表現為同一路径的再次訪問或来自不同 UA 的請求。
  3. 用浏览器禁用 JS 打開頁面,记錄缺失的正文和連結。
  4. 检查接口是否對爬虫請求做了差异化返回,這一点往往最容易被忽略。

让鏈路更稳的一些做法

  • 關键内容與主導航尽量服務端渲染,或做同构輸出,让源碼里就有可讀信息。
  • 分頁、詳情入口用真實的連結标簽承载,而不是纯点击事件。
  • canonical、robots meta 這類指令放在服務端輸出,不要靠脚本動態寫入。
  • 接口保持稳定响應,避免對正常抓取做額外拦截。
  • 懒加载尽量留一條不依赖交互的加载路径,或让首屏内容直接輸出。

還要提醒一点:渲染能力是逐步获得的。新站、内容更新频率低的站点,排到渲染队列的机會相對更少。把關键内容放進源碼,永遠比等渲染更省事,也更可控。

能被抓取的内容,往往先能被“不执行脚本”地讀到。