常见問题

蜘蛛池入口頁用 JavaScript 動態插入目标連結,搜尋蜘蛛還能發現吗?

入口頁把目标連結交给 JS 拼字符串再插入 DOM,是常见做法,但它會让發現路径變長甚至中断。本文說明抓取與渲染的区別、不同引擎的處理差异、几種“寫了等于没寫”的寫法,以及如何用日誌和渲染測試驗證蜘蛛是否真的拿到了連結。

常见問题

蜘蛛池入口頁用 JavaScript 動態插入目标連結,搜尋蜘蛛還能發現吗?

有些蜘蛛池入口頁為了防采集或者图省事,目标連結不寫在 HTML 里,而是用 JavaScript 拼成字符串再插進頁面。在浏览器里点開一切正常,但換成搜尋蜘蛛来抓,這條發現路径會明顯變長,甚至直接断掉。

抓取分两步:先取源碼,再决定要不要渲染

搜尋蜘蛛處理一個頁面通常有两步:第一步是抓取,把服務器返回的 HTML 源碼下载下来;第二步是渲染,把頁面放進渲染队列执行 JS,拿到最终的 DOM。第一步里,它看到的只是一段 <script> 里的字符串,不是連結;只有走到第二步,連結才可能出現。

問题在于渲染队列的成本遠高于普通抓取,優先級更低,等待時間從几小时到几天都有可能。對于入口頁這種本身權重不高、又需要快速传递信号的頁面,這個延迟會直接影响目标 URL 被發現的节奏。

不同搜尋引擎的處理差別很大

  • Google:渲染能力相對完整,但仍然要排队,且不保證每次都渲染。
  • Bing:部分场景支持渲染,覆盖率不稳定。
  • 百度:對 JS 渲染的支持有限,绝大多數情况下依赖源碼里的連結。
  • 其他中小引擎:基本只讀源碼,不做 JS 执行。

換句话说,把連結交给 JS,等于把發現權交给了對方“愿不愿意為你跑一次渲染”。這不是一個可以稳定依赖的前提。

几種典型的“寫了等于没寫”

  • innerHTML 把 <a> 标簽拼進某個容器,源碼里只有容器空壳。
  • 連結没有真實 href,只绑了 onclick 事件做跳轉。
  • 頁面先出骨架,連結靠接口返回後再异步插入,蜘蛛拿到的是空列表。
  • document.write 輸出連結,容易在渲染阶段被覆盖或忽略。
  • 連結放在 Shadow DOM 或閉包内部,渲染後也不一定暴露在可解析结构里。

這些寫法在浏览器里肉眼可见,在源碼里却搜不到目标 URL 的痕迹。入口頁的职责本来就是把發現路径缩短,一旦把連結藏進 JS,反而多设了一道關卡。

noscript 不是可靠的兜底

有人會把連結主要放在 <noscript> 里,指望不渲染时能讀到。實际效果並不稳定:部分引擎在開啟渲染後就不再讀取 noscript 内容,關閉渲染时又可能整段忽略。它最多算补充,不能当作主要通路来设計。

想保留 JS,也別让源碼里没有連結

  1. 能服務端渲染就服務端渲染,把包含連結的最终 HTML 直接返回。
  2. 源碼里至少保留一套静態 <a> 标簽指向目标 URL,JS 只做体驗增强。
  3. 連結使用真實 href,不要只靠点击事件跳轉。
  4. 避免把入口頁做成纯空壳,正文和連結先出,交互後加。
  5. 列表和翻頁用普通超連結,不要让“加载更多”按钮成為唯一的入口。

怎么驗證蜘蛛到底拿到没拿到

  • 用搜尋引擎提供的 URL 检查或渲染測試,查看渲染後的 HTML 里有没有目标連結。
  • 翻服務器日誌,確認搜尋蜘蛛是否真的請求過目标 URL,而不是只抓了入口頁。
  • 把源碼和渲染後的 DOM 對比,看連結是不是只存在于後者。
  • 如果日誌里目标 URL 長期没有任何抓取记錄,優先怀疑渲染這一环,而不是去調内容。
一個很简單的自检:把頁面源碼單獨複製出来,在里面搜一下目标 URL。如果搜不到,就不要預設搜尋蜘蛛一定能發現它。

小结

JS 動態插入連結並非绝對無效,但它属于“多一道關卡”的方案,适合有充足抓取预算和渲染容忍度的站点。對蜘蛛池入口頁這類以传递發現信号為主要任務的頁面,能直出就直出,把 JavaScript 留给确實需要交互的部分,連結的發現率會稳得多。