搜尋抓取

渲染方式與 URL 發現:連結寫進 JS 之後,搜尋蜘蛛還能不能走通

搜尋蜘蛛發現新地址的前提,是連結出現在它能讀到的 HTML 里。本文對比服務端渲染、静態生成與纯客戶端渲染對 URL 發現的影响,說明導航、面包屑、列表頁這些位置该怎么輸出連結,並给出用源碼對比、渲染測試和服務器日誌自查的具体步骤。

搜尋抓取

渲染方式與 URL 發現:連結寫進 JS 之後,搜尋蜘蛛還能不能走通

站内能被發現的地址數量,和頁面上寫了多少連結不是一回事。如果連結是在浏览器里由 JavaScript 生成之後才出現的,搜尋蜘蛛要先拿到頁面、执行脚本、等渲染完成,才可能看到這些地址。這一步能不能走通,取决于渲染方式和頁面结构。

原始 HTML 與渲染後的 DOM 不是一回事

搜尋蜘蛛抓取一個頁面时,最先拿到的是服務器直接返回的 HTML 源碼。多數情况下,連結是從這份源碼里被提取出来,進入待抓取队列的。如果源碼里只有一段脚本占位,真正的連結要等脚本执行完才出現,這些連結的發現就多了一道關卡:需要渲染。

渲染並非不可行,但它有前提:脚本要能正常加载、接口要能正常返回、頁面要能在合理時間内渲染完成。任何一环卡住,連結都可能看不到。相比之下,直接寫在 HTML 里、带 href 属性的 a 标簽,是最稳定的信号。

判断标准很简單:在不执行脚本的情况下查看頁面源代碼,能不能看到目标連結的地址。能看到,這條連結基本不依赖渲染;看不到,就要评估渲染环节是否可靠,以及有没有其他入口补上。

三種渲染方式對 URL 發現的影响

服務端渲染

服務器在返回 HTML 之前就把内容拼好,連結以 a 标簽形式出現在源碼里。蜘蛛拿到的第一份响應就包含導航、列表和分頁地址,不需要額外等待。對 URL 發現来说,這是最省事的做法。

静態生成與预渲染

頁面在构建阶段生成 HTML,連結同样寫在源碼里,适合栏目頁、文章頁這類數量可枚举的内容。需要注意的是新發布的地址是否及时重新生成,否則新連結不會出現在任何一份 HTML 中,只能靠 Sitemap 或其他入口补上。

纯客戶端渲染

HTML 里几乎是空壳,連結全部由脚本生成。這種情况下,URL 發現依赖渲染队列的調度,速度更慢,也不保證每個頁面都能渲染成功。常见的折中做法是给關键導航和列表頁做服務端渲染或预渲染,只把交互性强的部分留给客戶端。

内鏈结构里最该检查的几個位置

  • 主導航與頁脚:用 a 标簽輸出真實地址,避免用点击事件或脚本跳轉代替。
  • 面包屑:它既是抓取路径,也是层級關系的說明,尽量静態輸出。
  • 列表頁與分頁:新地址大多從這里進入抓取队列,分頁連結要能直接点到。
  • 相關推荐與聚合入口:如果由接口异步加载,至少保證頁面上有一份可讀的連結兜底。

怎么自查

  1. 禁用脚本打開頁面,看導航和列表里是否還有可点的連結。
  2. 查看源代碼,搜尋 href 出現的次數,和頁面上實际連結數對比。
  3. 用抓取測試工具查看渲染後的结果,對比渲染前後連結數量的差异。
  4. 在服務器日誌里確認蜘蛛是否請求過某個新地址。如果它连請求都没有,問题多半出在發現环节,而不是抓取环节。

几個容易踩的坑

  • 用带 # 的 hash 路由做導航,蜘蛛看到的往往是同一個地址,無法区分不同内容。
  • 脚本里拼接的相對路径大小寫與真實地址不一致,产生大量重复或失效地址。
  • 渲染超时或接口报错,頁面停在加载狀態,連結既没被發現,也没有明确报错。
  • 把連結寫成按钮,样式上像連結,语义上只是可点击元素。
可爬性應该排在渲染方案之前考虑:先保證連結能静態輸出,再决定哪些部分交给脚本。

如果站内确實有一部分連結只能由脚本生成,也不必完全否定,但要给這些地址留第二條通道:在 Sitemap 里申报、在關键位置补静態入口、在日誌里盯住它們是否被請求。URL 發現不是一次性的工作,渲染方式變了、模板改版了,發現路径也會跟着變。定期把源碼和日誌對一遍,比等到收錄出問题再回头排查要省事得多。