抓取和渲染,在蜘蛛那里是两件事
很多人把「蜘蛛来過」理解成一個動作:請求、下载、看懂頁面。實际流程至少能拆成两段。第一段是普通的 HTTP 抓取,服務器返回什么 HTML,蜘蛛就先拿到什么;第二段是把頁面丢進渲染队列,用浏览器内核执行 JavaScript,等 DOM 稳定之後再讀一遍。两段之間可能只隔几分钟,也可能隔上好几天。
這個時間差直接决定了一件事:如果 URL 只存在于 JS 执行之後的 DOM 里,它被發現的時間就要往後推。
第一趟:原始 HTML 里有什么,就先認什么
第一次請求返回的源碼,如果只有一個空容器节点加一段脚本引用,那這一趟能讀到的信息就非常有限。蜘蛛不會在這一步替你执行脚本,它只是把源碼里現成的线索收走。
能在第一趟被發現的
- 服務端直接輸出在 HTML 里的 a 标簽連結;
- Sitemap 中列出的 URL;
- RSS、Atom 等订阅文件里的條目;
- HTTP 响應头中的重定向目标與 Link 信息。
要等第二趟的
- 由前端路由在浏览器里生成的内鏈;
- 点击「加载更多」才會出現的列表項;
- 依赖接口返回資料拼出来的詳情入口。
這里的区別不是「能不能被抓到」,而是「什么时候被抓到」。前者進入常規抓取队列,後者得先過渲染這一關。
渲染队列慢在哪里
渲染比纯抓取贵得多:要起浏览器進程、下载脚本和样式、执行代碼、等接口回包。资源有限,站点一多就必然排队。
- 頁面脚本多、体积大,單頁渲染耗时更長,队列被占用的時間也長;
- 渲染失敗或超时的頁面,通常不會立刻重新排队;
- 层級深、外部入口少的 URL,排位更靠後,等待更明顯。
另外要分清:這里讨论的是發現和获取的节奏,不是收錄结果。渲染成功也不等于頁面一定會被索引。
让關键連結出現在原始 HTML 里
做法不复杂,核心是別把發現入口全交给 JS。可以按下面的顺序排查和調整:
- 栏目頁、列表頁、詳情頁之間的互相連結,優先用服務端渲染或静態輸出。
- 交互可以保留 JS,但基础導航用普通 a 标簽兜底。
- 分頁和「下一頁」给出真實 URL,而不是绑定点击事件。
- Sitemap 只提交确實需要被發現的 URL,並尽量與站内可见連結保持一致。
- 不必整站 SSR,至少把導航、面包屑、列表連結放進首屏源碼。
這样做的好處是可预期的:蜘蛛第一趟就能顺着連結往下走,渲染队列只承担补充角色,而不是唯一的入口。
怎么確認自己有没有踩坑
- 關閉 JS,或只用源碼抓取工具跑一遍,看能顺連結点到第几层。
- 對比源碼里的連結數量和渲染後 DOM 里的連結數量,差得越多,依赖越重。
- 查看抓取日誌,看同一批 URL 是否在渲染請求里才出現,是否比首轮抓取晚很多。
- 抽查若干深层頁,確認它們至少有一條来自原始 HTML 的入口。
蜘蛛並不是看不见 JS 頁面,而是它走在两條不同的队列上。把關键連結放回第一趟就能讀到的地方,URL 的發現节奏會稳定很多。
最後补一句服務器侧的因素:渲染請求同样要占用连接和带宽。如果源站响應偏慢,渲染阶段的等待會叠加在抓取等待之上,整体节奏更慢。保持响應時間稳定、避免長時間無响應,對两趟流程都有帮助。