搜尋抓取

連結寫在 JavaScript 里:蜘蛛什么时候才看得到並繼續往下走

很多站点的連結由 JavaScript 動態生成,人点得動,蜘蛛在第一轮 HTML 里却看不到。本文讲清抓取與渲染两步之間的時間差、几種常见寫法带来的延迟,以及把關键連結放回 HTML 的具体做法,並给出可落地的自查方法。

搜尋抓取

連結寫在 JavaScript 里:蜘蛛什么时候才看得到並繼續往下走

不少站点的連結並不是寫在 HTML 里,而是由 JavaScript 在浏览器中生成。人看起来一切正常,点击顺畅、跳轉飞快,但對搜尋蜘蛛来说,URL 發現這件事可能被推迟,甚至被漏掉。這篇不讨论「能不能被抓」,只讨论当連結由脚本生成时,蜘蛛發現地址的节奏會發生什么變化,以及站点能做的調整。

抓取和渲染不是同一步

蜘蛛取回一個頁面时,先拿到的是服務器返回的原始 HTML。如果連結只存在于脚本执行之後的 DOM 里,這一轮它就看不到這些地址。

搜尋引擎通常會把這些頁面排進渲染队列,等资源允许时再执行脚本,渲染完成後才提取連結,並把新地址放進下一轮抓取。也就是说,連結從「被渲染出来」到「真正被訪問」,中間還隔着一次排队。頁面层級越深、站点越大,這個時間差越明顯。

連結由脚本生成时,通常會看到什么現象

  • 新頁面發布後,日誌里迟迟没有抓取记錄,尤其是列表頁之後的二三层頁面;
  • 首頁和主列表頁被抓得很勤,詳情頁數量增長却非常缓慢;
  • 分頁、篩選、折叠面板里的地址,几乎不出現在抓取日誌中;
  • 同一批老頁面反复被抓,新增 URL 却寥寥無几。

几種常见寫法與它們的代價

  • 点击事件跳轉:用 div 或 span 绑定点击,地址寫在脚本里,HTML 中没有任何 href,蜘蛛没有可跟随的目标。
  • 前端路由:靠 history 接口換地址,服務器對所有路径都返回同一個壳頁面,連結全部由脚本拼出。
  • 無限滚動:内容随滚動加载,没有可翻頁的真實地址,蜘蛛很难走到列表深處。
  • 懒加载区块:Tab、折叠面板里的連結只有交互後才插入 DOM,預設狀態下一片空白。
  • href 為空或寫成脚本伪协议:看着像連結,實际没有可抓的目标地址。

把關键連結放回 HTML

  1. 首屏與主内容区尽量服務端渲染或静態生成,導航、面包屑、列表項輸出真實可点的連結。
  2. 分頁用真實 URL,並且這條地址要能在 HTML 源碼里被讀到,而不是只在点击时才生成。
  3. 無限滚動之外保留一條可翻頁的备用路径,比如「查看全部」或带頁碼的地址。
  4. 重要区块不要只放在預設隐藏的 Tab 里,考虑给它一條獨立地址或锚点入口。
  5. 预渲染可以作為過渡手段,但要让返回给蜘蛛的内容和真實頁面保持一致,避免形成两套内容。

怎么判断自己中招了

不需要复杂工具,几個對照就能看出端倪:

  • 用禁用脚本的方式請求頁面,對比有無脚本时 HTML 里的連結數量;
  • 看服務器日誌里是否存在渲染服務或第三方渲染来源的請求;
  • 观察抓取統計中「已發現未抓取」的 URL 是否長期堆积、迟迟不動;
  • 抽查几個深层頁面,確認它是否有来自 HTML 的入站連結。
渲染能帮蜘蛛看到更多内容,但它不是 URL 發現的捷径。能直接出現在 HTML 里的連結,永遠比等渲染更稳。

节奏上的取舍

並不是所有連結都必须塞進 HTML。導航、分類入口、核心内容這些值得;一些纯交互型的小组件可以接受被延迟發現。判断标准很简單:這個地址如果晚几天才被發現,會不會影响站点的主要收錄结构。會,就放回 HTML;不會,留在脚本里問题不大。

一個容易忽略的细节

即便連結已经在 HTML 里,如果它被埋在几百個同质連結之後,或者只出現在頁脚最末端,實际被走到的顺序依然靠後。把重要入口放在离首頁更近的位置,比單纯增加連結數量更有意义。