常见問题

入口頁連結靠 JavaScript 動態注入,搜尋蜘蛛還能發現目标 URL 吗

入口頁的連結如果只在脚本执行後才寫進 DOM,搜尋蜘蛛要先抓源碼、再渲染才能看到。本文說明渲染抓取的時間與预算限制、哪些寫法最容易让連結“隐身”,以及服務端輸出、sitemap 补充等更稳的做法,並给出驗證渲染结果的方法。

常见問题

入口頁連結靠 JavaScript 動態注入,搜尋蜘蛛還能發現目标 URL 吗

把目标 URL 直接寫進入口頁的 HTML 源碼,和等頁面脚本跑完再動態插入到 DOM 里,對搜尋蜘蛛来说是两條完全不同的路径。前者在抓取阶段就能看到連結,後者要先排進渲染队列,能不能被發現,取决于渲染有没有跑、跑到哪一步。

源碼里的連結和執行时生成的連結不是一回事

搜尋蜘蛛處理頁面大致分两步:先抓取 HTML 源碼,再把符合條件的頁面放進渲染队列,用無头浏览器执行脚本。連結如果只存在于第二步的结果里,第一步就什么都看不到。

渲染队列有獨立的調度和预算。一個頁面被抓過,不代表它一定會被渲染;被渲染了,也不代表脚本一定能执行完。JS 動態注入的連結就卡在這個不确定的环节上。

渲染抓取為什么會漏掉目标 URL

  • 渲染有時間上限,脚本依赖接口、多重异步、外部资源慢,没执行完就被結束,連結自然不存在。
  • 渲染和抓取共用一套资源约束,單頁脚本体积過大或 DOM 节点過多,可能被截断處理。
  • 渲染结果按周期缓存,頁面结构改動频繁时,蜘蛛看到的可能是舊版本。
  • 同一頁面重复出現相同的目标 URL,容易被当作重复模板降權,而不是多一次机會。

這些寫法最容易让連結“隐身”

  1. 把連結绑在点击、滚動、悬停事件上,不交互就不插入 DOM。
  2. 用 setTimeout 延迟寫入,等待時間越長,渲染窗口越可能已经關閉。
  3. 先請求接口拿到資料再拼 href,接口失敗或超时,頁面上什么都不剩。
  4. 用 div 加 onclick、或用路由库的 pushState 代替标准的 a 标簽。
  5. 列表很長时使用虚拟滚動,视口之外的部分根本没有渲染出来。
  6. 依赖登入態、Cookie 或特定 UA 才輸出連結。

提高可發現性的几個務實做法

  • 服務端輸出關键連結:让入口頁返回的 HTML 源碼里就带着可抓的 href,這是最稳的一條路。
  • 补一條 sitemap 通道:把重要的目标 URL 同时放進 sitemap,让發現路径不完全依赖入口頁。
  • 用标准連結:a 标簽的 href 寫绝對地址,不要留空、不要寫 javascript: 或只寫锚点。
  • 减少前置依赖:把渲染前必须完成的接口請求压到最少,首屏資料尽早返回。
  • 控制連結數量:單個入口頁渲染後輸出的連結別過量,避免和抓取预算互相挤压。

怎么確認渲染後到底有没有連結

只看 curl 或查看源碼是不够的,那只能看到第一步的结果。更實用的做法是對比“源碼 HTML”和“渲染後的 DOM”,看目标連結是否出現在後者里;再配合日誌观察目标 URL 有没有真的被請求過。如果源碼里没有、渲染後才有,同时日誌里目标 URL 長期没有訪問记錄,基本可以判断渲染這條路没走通。

需要說明的是,渲染抓取是补充手段而不是保證。連結被發現、被抓取、被收錄是几個獨立环节,中間任何一步的判断都可能让结果停下来,不要把它当成确定性的通道。

總结一句:入口頁的連結能寫在 HTML 源碼里就別只留给脚本。動態渲染可以增强頁面体驗,但把它当成目标 URL 唯一的發現入口,風險不小。