站内能被發現的地址數量,和頁面上寫了多少連結不是一回事。如果連結是在浏览器里由 JavaScript 生成之後才出現的,搜尋蜘蛛要先拿到頁面、执行脚本、等渲染完成,才可能看到這些地址。這一步能不能走通,取决于渲染方式和頁面结构。
原始 HTML 與渲染後的 DOM 不是一回事
搜尋蜘蛛抓取一個頁面时,最先拿到的是服務器直接返回的 HTML 源碼。多數情况下,連結是從這份源碼里被提取出来,進入待抓取队列的。如果源碼里只有一段脚本占位,真正的連結要等脚本执行完才出現,這些連結的發現就多了一道關卡:需要渲染。
渲染並非不可行,但它有前提:脚本要能正常加载、接口要能正常返回、頁面要能在合理時間内渲染完成。任何一环卡住,連結都可能看不到。相比之下,直接寫在 HTML 里、带 href 属性的 a 标簽,是最稳定的信号。
判断标准很简單:在不执行脚本的情况下查看頁面源代碼,能不能看到目标連結的地址。能看到,這條連結基本不依赖渲染;看不到,就要评估渲染环节是否可靠,以及有没有其他入口补上。
三種渲染方式對 URL 發現的影响
服務端渲染
服務器在返回 HTML 之前就把内容拼好,連結以 a 标簽形式出現在源碼里。蜘蛛拿到的第一份响應就包含導航、列表和分頁地址,不需要額外等待。對 URL 發現来说,這是最省事的做法。
静態生成與预渲染
頁面在构建阶段生成 HTML,連結同样寫在源碼里,适合栏目頁、文章頁這類數量可枚举的内容。需要注意的是新發布的地址是否及时重新生成,否則新連結不會出現在任何一份 HTML 中,只能靠 Sitemap 或其他入口补上。
纯客戶端渲染
HTML 里几乎是空壳,連結全部由脚本生成。這種情况下,URL 發現依赖渲染队列的調度,速度更慢,也不保證每個頁面都能渲染成功。常见的折中做法是给關键導航和列表頁做服務端渲染或预渲染,只把交互性强的部分留给客戶端。
内鏈结构里最该检查的几個位置
- 主導航與頁脚:用 a 标簽輸出真實地址,避免用点击事件或脚本跳轉代替。
- 面包屑:它既是抓取路径,也是层級關系的說明,尽量静態輸出。
- 列表頁與分頁:新地址大多從這里進入抓取队列,分頁連結要能直接点到。
- 相關推荐與聚合入口:如果由接口异步加载,至少保證頁面上有一份可讀的連結兜底。
怎么自查
- 禁用脚本打開頁面,看導航和列表里是否還有可点的連結。
- 查看源代碼,搜尋 href 出現的次數,和頁面上實际連結數對比。
- 用抓取測試工具查看渲染後的结果,對比渲染前後連結數量的差异。
- 在服務器日誌里確認蜘蛛是否請求過某個新地址。如果它连請求都没有,問题多半出在發現环节,而不是抓取环节。
几個容易踩的坑
- 用带 # 的 hash 路由做導航,蜘蛛看到的往往是同一個地址,無法区分不同内容。
- 脚本里拼接的相對路径大小寫與真實地址不一致,产生大量重复或失效地址。
- 渲染超时或接口报错,頁面停在加载狀態,連結既没被發現,也没有明确报错。
- 把連結寫成按钮,样式上像連結,语义上只是可点击元素。
可爬性應该排在渲染方案之前考虑:先保證連結能静態輸出,再决定哪些部分交给脚本。
如果站内确實有一部分連結只能由脚本生成,也不必完全否定,但要给這些地址留第二條通道:在 Sitemap 里申报、在關键位置补静態入口、在日誌里盯住它們是否被請求。URL 發現不是一次性的工作,渲染方式變了、模板改版了,發現路径也會跟着變。定期把源碼和日誌對一遍,比等到收錄出問题再回头排查要省事得多。