很多人看日誌时會遇到一種情况:服務器明明返回了 200,頁面也确實被蜘蛛請求過,但頁面里的新連結過了很久才出現在抓取记錄里,甚至一直没出現。原因往往不在抓取环节,而在抓取之後的渲染排队。
抓取和渲染是两個阶段
對蜘蛛来说,一次完整的處理通常分成两步:先把 HTML 拉回来,再决定是否放進渲染队列,用浏览器内核执行頁面脚本,拿到最终形態的 DOM。第一步的速度取决于你的服務器和網絡,第二步取决于蜘蛛自己的渲染资源,以及全站有多少頁面在排队等待渲染。
關键在于:只有在渲染完成後才出現在 DOM 里的連結,才可能在渲染這一步被看到。如果渲染没有發生,或者發生在很晚之後,這些 URL 的發現時間就會整体後移。
渲染排队怎样拖慢 URL 發現
- 連結依赖前端路由或接口返回後再插入 DOM,初始 HTML 里没有痕迹。
- 頁面脚本体积大、依赖多,渲染一次的成本高,容易被排到队列後面。
- 同一批模板生成的頁面大量重复排队,渲染预算被摊薄。
- 渲染失敗的頁面通常不會立刻重排,連結就跟着一起被搁置。
表現上,它不像 5xx 那样醒目:抓取是成功的,只是“看到了却没讀懂”。
哪些頁面更容易在渲染环节掉队
列表頁、聚合頁、篩選頁通常是重灾区,因為新 URL 大多由它們带出来。其次是靠组件懒加载渲染的導航和推荐位。相對安全的是服務端直出的静態頁面,連結寫在 HTML 里,抓到即看到。
让關键 URL 出現在初始 HTML 里
- 把主導航、面包屑、分類列表的核心連結改成服務端輸出,不依赖脚本插入。
- 列表頁首屏的分頁入口、下一頁連結,直接寫在 HTML 中,而不是点击後再請求。
- 為重要栏目提供一份纯 HTML 的入口頁,把連結集中放在那里,降低渲染依赖。
- 减少首屏必须执行的脚本量,让渲染更快完成,减少排队時間。
- 如果确實要用 JS 生成連結,尽量在 HTML 中保留等價的可爬連結作為兜底。
這些做法的共同思路是:把 URL 發現這件事,從渲染阶段挪回抓取阶段。
怎么驗證是不是渲染問题
關閉浏览器脚本,直接請求頁面源碼,看目标連結是否還在。如果源碼里没有、渲染後才有,就基本可以確認。再對照抓取日誌里该頁面的請求時間和新 URL 首次被抓的時間差,判断延迟是排队造成還是別的原因。
抓取成功只說明 HTML 到手,連結是否被發現,還要看渲染這一關有没有過、過得快不快。
把連結放回初始 HTML,既减少了對渲染资源的依赖,也让 URL 發現路径更短、更稳定。