把目标 URL 直接寫進入口頁的 HTML 源碼,和等頁面脚本跑完再動態插入到 DOM 里,對搜尋蜘蛛来说是两條完全不同的路径。前者在抓取阶段就能看到連結,後者要先排進渲染队列,能不能被發現,取决于渲染有没有跑、跑到哪一步。
源碼里的連結和執行时生成的連結不是一回事
搜尋蜘蛛處理頁面大致分两步:先抓取 HTML 源碼,再把符合條件的頁面放進渲染队列,用無头浏览器执行脚本。連結如果只存在于第二步的结果里,第一步就什么都看不到。
渲染队列有獨立的調度和预算。一個頁面被抓過,不代表它一定會被渲染;被渲染了,也不代表脚本一定能执行完。JS 動態注入的連結就卡在這個不确定的环节上。
渲染抓取為什么會漏掉目标 URL
- 渲染有時間上限,脚本依赖接口、多重异步、外部资源慢,没执行完就被結束,連結自然不存在。
- 渲染和抓取共用一套资源约束,單頁脚本体积過大或 DOM 节点過多,可能被截断處理。
- 渲染结果按周期缓存,頁面结构改動频繁时,蜘蛛看到的可能是舊版本。
- 同一頁面重复出現相同的目标 URL,容易被当作重复模板降權,而不是多一次机會。
這些寫法最容易让連結“隐身”
- 把連結绑在点击、滚動、悬停事件上,不交互就不插入 DOM。
- 用 setTimeout 延迟寫入,等待時間越長,渲染窗口越可能已经關閉。
- 先請求接口拿到資料再拼 href,接口失敗或超时,頁面上什么都不剩。
- 用 div 加 onclick、或用路由库的 pushState 代替标准的 a 标簽。
- 列表很長时使用虚拟滚動,视口之外的部分根本没有渲染出来。
- 依赖登入態、Cookie 或特定 UA 才輸出連結。
提高可發現性的几個務實做法
- 服務端輸出關键連結:让入口頁返回的 HTML 源碼里就带着可抓的 href,這是最稳的一條路。
- 补一條 sitemap 通道:把重要的目标 URL 同时放進 sitemap,让發現路径不完全依赖入口頁。
- 用标准連結:a 标簽的 href 寫绝對地址,不要留空、不要寫 javascript: 或只寫锚点。
- 减少前置依赖:把渲染前必须完成的接口請求压到最少,首屏資料尽早返回。
- 控制連結數量:單個入口頁渲染後輸出的連結別過量,避免和抓取预算互相挤压。
怎么確認渲染後到底有没有連結
只看 curl 或查看源碼是不够的,那只能看到第一步的结果。更實用的做法是對比“源碼 HTML”和“渲染後的 DOM”,看目标連結是否出現在後者里;再配合日誌观察目标 URL 有没有真的被請求過。如果源碼里没有、渲染後才有,同时日誌里目标 URL 長期没有訪問记錄,基本可以判断渲染這條路没走通。
需要說明的是,渲染抓取是补充手段而不是保證。連結被發現、被抓取、被收錄是几個獨立环节,中間任何一步的判断都可能让结果停下来,不要把它当成确定性的通道。
總结一句:入口頁的連結能寫在 HTML 源碼里就別只留给脚本。動態渲染可以增强頁面体驗,但把它当成目标 URL 唯一的發現入口,風險不小。