蜘蛛第一次拿到的往往是空壳
單頁應用把渲染工作交给了浏览器:一次請求返回的 HTML 通常只有固定的头部、一個空的挂载节点和几段打包脚本,正文和連結都要等 JavaScript 执行、接口返回之後才出現。蜘蛛抓取的第一份内容就是這份外壳,里面既没有可讀文本,也没有指向路由的 a 标簽,路由背後的 URL 自然也就没被登记進来。
三種路由寫法,被發現的难度不同
- history 模式:地址看起来是正常的路径,例如 /list/2,本身具备被抓取的形式,难点在于頁面里要先有指向它的連結。
- hash 模式:地址里带 #,片段部分通常不作為獨立 URL 處理,路由再多也可能只對應一個抓取入口。
- 查询參數路由:形如 ?page=3 的寫法容易被抓取,但參數一旦叠加,容易生出大量近似地址。
寫法本身没有绝對的好坏,關键在于能否在 HTML 层面暴露足够多、指向明确的連結。
把連結寫回 href
很多 SPA 的導航是可点击的,但對蜘蛛来说不可讀:点击事件挂在 div 上,地址靠脚本 push 進去,HTML 里什么也没留下。要改變這一点,思路其實很朴素——让每個需要被發現的路由,都有一個真實的連結地址。
- 導航與列表項用 a 标簽承载 href,而不是给 div 绑定点击事件。
- href 寫真實路径,避免 javascript:void(0) 或只做頁内锚点跳轉。
- 滚動加载之外,给出可訪問的分頁地址,让靠後的内容有獨立入口。
- 路由切換时同步更新 title 與主要内容区域,不要只替換一小块组件。
渲染成本的另一面
服務端渲染或预渲染能把首屏 HTML 直接吐出来,蜘蛛不必执行脚本就能讀到内容和連結,這是最省事的一條路。但它也有代價:每個需要跑脚本的頁面都會占用額外的抓取资源,接口响應慢时還會把整体抓取時間拉長。因此常见的做法是分层處理——首頁、栏目頁、詳情頁這類需要被發現的内容走服務端輸出,交互密集的個人中心、购物车之類留在客戶端渲染。
渲染不是免費的:让每個 URL 都跑一遍脚本,等于把發現成本轉嫁给抓取资源,能静態輸出的路径尽量静態輸出。
几個自查動作
- 临时關閉 JavaScript 打開頁面,看看還剩多少可讀文本和可点連結。
- 查看頁面源碼,確認關键連結出現在源碼里,而不是執行时才注入。
- 翻服務器日誌,看蜘蛛抓到的是各個路由路径,還是反复訪問同一個外壳地址。
- 把重要路由寫進 Sitemap,作為内鏈之外的一條补充發現通道。
SPA 的抓取問题,说到底不是技術選型的問题,而是連結有没有以蜘蛛讀得到的形式出現。把發現路径铺好,後面的抓取节奏才有讨论的基础。