前端框架普及之後,服務器返回的 HTML 常常只剩一個空容器,正文和連結都要等 JavaScript 跑完才出現。蜘蛛在這方面比以前進步很多,但它走的顺序和用戶不同:先下载 HTML,再去排队执行脚本,中間任何环节出問题,停在脚本里的連結就不會進入下一步。
第一份 HTML 决定第一次分叉
蜘蛛請求一個 URL 时,最先拿到的是服務端直接返回的源碼。如果導航、栏目入口、詳情頁連結都寫在這份源碼里,路径在這一层就铺開了;如果它們全部由 JS 在浏览器端生成,第一份源碼里就是空的,蜘蛛只能等渲染。等待不是問题,問题是等待有成本,而且不保證成功。
渲染是排队發生的,不是同步的
渲染阶段的执行依赖不少外部條件:
- 渲染用的脚本和样式如果被 robots.txt 屏蔽,蜘蛛看不到完整頁面;
- 第三方統計、字体、地图等脚本加载慢或超时,會拖住整頁的渲染;
- 渲染任務有排队,頁面越依赖脚本,真正拿到内容的延迟越大;
- 需要登入、需要点击才出現的連結,基本不會進入抓取路径。
所以,一個在浏览器里看起来完全正常的頁面,可能在蜘蛛那一侧只呈現出一個框架结构。
用 a 标簽還是用点击事件
同样是跳轉,寫法不同,结果差別很大。寫成 <a href="/detail/123">,蜘蛛在解析 HTML 时就能拿到連結;寫成 span 加 onclick 跳轉,或者靠 JS 绑定事件,連結對蜘蛛来说等于不存在。用 history.pushState 做客戶端路由时也一样,地址栏變了,但 HTML 里没有對應的 href,蜘蛛没有可跟随的目标。
另一種常见情况是連結确實存在,但被包在條件判断里,比如只有鼠标悬停、只有滚動到可视区域才插入 DOM。蜘蛛的渲染不一定触發這些條件。
懒加载和無限滚動要留出口
图片懒加载問题不大,内容連結的懒加载就要留意。列表頁如果只在滚動到底部时才追加下一頁,蜘蛛很难走完。比較稳妥的做法是把分頁做成带真實 URL 的連結,滚動加载只是给用戶的补充,而不是唯一入口。
怎么確認蜘蛛真的走通了
- 用可以查看渲染结果的工具检查頁面,對比初始 HTML 和渲染後的 HTML,看連結在哪個阶段出現。
- 在服務器日誌里搜尋子頁面路径,確認有没有来自蜘蛛的請求,而不是只有首頁的訪問记錄。
- 检查 robots.txt 是否挡住了渲染必需的 JS、CSS 资源。
- 排查脚本错誤和超时,尤其是首屏依赖的第三方资源。
判断标准不是頁面在浏览器里能不能打開,而是初始 HTML 或渲染结果里有没有可跟随的 href。
让两條路径都能走
關键導航、栏目入口、詳情頁連結尽量在服務端渲染輸出,或者至少保證初始 HTML 中存在連結。對重内容頁面,可以考虑服務端渲染或预渲染,把主体内容先给出去。連結统一用标准 a 标簽承载,客戶端路由只作為增强。這样無论蜘蛛走初始 HTML 還是走渲染路径,都能找到下一步。
抓取路径断在渲染阶段的信号
如果日誌里首頁和几個主要栏目頁抓取正常,更深一层的 URL 却長期没有记錄,而站点又是重度依赖 JS 的结构,那基本可以把排查方向放在渲染环节,而不是外鏈或權重。先把這個环节理顺,再谈抓取频率和收錄,顺序會更顺一些。