越来越多站点把列表、詳情甚至整站導航交给 JavaScript 渲染。结果是在浏览器里一切正常,在蜘蛛那邊却只拿到一個空壳 HTML。要排查這類問题,先得理解一件事:搜尋蜘蛛處理一個 URL,往往不是一次抓取,而是两次。
第一次:拉取原始 HTML
蜘蛛首先請求服務器返回的源碼,也就是未执行脚本的那份 HTML。這個阶段它能讀到服務端輸出的标题、正文、連結、结构化資料和 meta 标簽。如果連結在源碼里就已经存在,蜘蛛可以直接顺着走;如果連結是脚本执行後才插入 DOM 的,第一次抓取时它看不到。
一個實用的判断标准是:關掉浏览器 JS,頁面還剩多少可讀内容和可点連結。剩下的那部分,就是蜘蛛在第一時間能拿到的東西。
第二次:進入渲染队列
對于確認依赖脚本的頁面,搜尋引擎會安排一次渲染,用無头浏览器执行 JS 並讀取渲染後的 DOM。這一步有几個特点:
- 排队:渲染资源有限,通常是先發現、後渲染,存在延迟,也不是每個 URL 都能排上。
- 超时:脚本执行、接口請求、图片與字体加载都有時間上限,超出的部分拿不到。
- 不交互:不會点按钮、不會滚動到底、不會關閉彈窗、不會填表單。
換句话说,渲染阶段能救回一部分内容,但它不是保險,更像一次补考。
常见的抓取断点
1. 内容完全靠接口异步拉取
頁面源碼里只有容器和脚本,資料要等接口返回才出現。如果接口响應慢、需要特定請求头,或者對爬虫 UA 返回不同结果,渲染时同样可能拿不到東西。
2. 連結依赖点击或滚動
加载更多按钮、無限滚動、Tab 切換,都會让後續内容在渲染阶段也不出現在首屏。分頁入口如果只是脚本事件而不是真實連結,抓取路径就断在這里。
3. 懒加载與占位内容
图片、评论区等资源進入视口才加载,渲染器不一定滚動,于是這部分可能長期不參與抓取。
4. 登入、驗證碼與地区限制
被拦住的頁面在源碼阶段就可能拿到 403 或跳到登入頁,後續渲染更無從谈起。
5. 渲染脚本本身报错
JS 抛错、依赖的外鏈资源被墙、跨域請求被拒,都會让 DOM 停在半成品狀態。
怎么確認蜘蛛到底看到了什么
- 用搜尋引擎提供的 URL 检查工具,對比原始 HTML 與渲染後 HTML 两種视图。
- 在服務器日誌里看该 URL 的抓取次數與狀態碼,渲染抓取有时表現為同一路径的再次訪問或来自不同 UA 的請求。
- 用浏览器禁用 JS 打開頁面,记錄缺失的正文和連結。
- 检查接口是否對爬虫請求做了差异化返回,這一点往往最容易被忽略。
让鏈路更稳的一些做法
- 關键内容與主導航尽量服務端渲染,或做同构輸出,让源碼里就有可讀信息。
- 分頁、詳情入口用真實的連結标簽承载,而不是纯点击事件。
- canonical、robots meta 這類指令放在服務端輸出,不要靠脚本動態寫入。
- 接口保持稳定响應,避免對正常抓取做額外拦截。
- 懒加载尽量留一條不依赖交互的加载路径,或让首屏内容直接輸出。
還要提醒一点:渲染能力是逐步获得的。新站、内容更新频率低的站点,排到渲染队列的机會相對更少。把關键内容放進源碼,永遠比等渲染更省事,也更可控。
能被抓取的内容,往往先能被“不执行脚本”地讀到。