常见問题

蜘蛛池入口頁的連結由 JavaScript 渲染,搜尋蜘蛛抓取时實际發生了什么

很多蜘蛛池入口頁用 JavaScript 動態拼出目标 URL,這類連結對搜尋蜘蛛来说多了一道渲染工序。本文說明原始 HTML 與渲染後 HTML 的区別、常见寫法里哪些連結等于不可發現,以及更稳妥的服務端輸出方式,並给出用日誌驗證的判断方法。

常见問题

蜘蛛池入口頁的連結由 JavaScript 渲染,搜尋蜘蛛抓取时實际發生了什么

先说结论:JS 渲染的連結,發現门槛明顯更高

蜘蛛池入口頁為了防采集、方便動態換鏈,常用 JavaScript 把目标 URL 拼到頁面上。對搜尋蜘蛛来说,這一步等于多加了一道工序:爬虫第一次拿到的响應是原始 HTML,如果目标 URL 不在里面,這條連結就不會出現在最基础的發現鏈路中,只能等它進入渲染环节再處理。而渲染环节的排期、执行率和超时策略由各家引擎自己决定,站点無法控制。

所以問题不是“能不能被發現”,而是“被發現的時間、概率和可控性都變差了”。

不同搜尋蜘蛛對 JS 的處理差別很大

  • 主流引擎通常具备渲染能力,但往往是第二轮抓取:先抓原始 HTML,再排队执行 JS,延迟從几小时到几周都可能出現。
  • 渲染资源比普通抓取紧張得多,URL 量級一大,队列积压會很嚴重。
  • 部分轻量爬虫、第三方抓取工具完全不执行 JS,只看原始响應。
  • 如果 robots.txt 把入口頁依赖的 JS、CSS 或資料接口屏蔽掉,渲染會直接失敗,頁面渲染出来是空壳。

這些 JS 寫法,基本等于让目标 URL 不可發現

  • 用 innerHTML 拼接字符串生成連結,但生成出来的元素没有真正的 href 属性。
  • 寫成 href="javascript:void(0)",再靠点击事件跳轉,抓取端看不到可跟随的地址。
  • 連結先渲染成占位文字,用戶点击时才通過脚本替換地址。
  • 連結依赖 XHR / fetch 拉接口後再插入,而该接口被 robots 限制,或需要特定 Cookie、特定 Referer 才返回資料。
  • 前端路由用哈希(#/detail 這類),它不會产生新的 URL,抓取端只認 # 之前的部分。
  • 懒加载:連結要滚動到底部或点击“加载更多”才出現,渲染器不一定触發這個動作。
  • 頁面加载過慢、脚本报错,渲染任務超时後可能被直接放弃。

判断标准其實很简單:把入口頁的 HTML 源碼存下来,直接搜尋目标 URL。搜得到,說明它進入了最基础的發現鏈路;搜不到,就只能指望渲染,主動權已经不在自己手里。

如果一定要用 JS,做法上怎么更稳一点

  1. 服務端直出基础連結。入口頁首屏用普通 a 标簽輸出绝對地址,JS 只做增强,不做唯一来源。
  2. 保證連結是真實可点击的锚点,href 里寫完整的 https 地址,而不是靠事件绑定。
  3. 需要換鏈、防采集时,把變化放在服務端模板或 CDN 层,而不是让客戶端脚本临时拼地址。
  4. 分頁、列表頁尽量用常規連結结构,避免整站連結都靠异步渲染。
  5. sitemap 只做补充渠道,不要当成唯一發現手段。
  6. 不要指望 noscript 里的連結一定被当作正常連結處理,它更适合做用戶提示,不适合做發現主通道。

用日誌驗證,而不是靠感觉

看資料时容易踩的坑是:入口頁抓取量很大,就以為目标 URL 也在被發現。實际要看的是目标 URL 有没有出現在訪問日誌里。几個可用的观察点:

  • 日誌里有没有對入口頁依赖的 JS、CSS 文件的請求,這能間接說明抓取端是否具备渲染行為。
  • 渲染請求的 User-Agent 有时和普通抓取相同,不能只靠 UA 区分,要结合請求序列判断。
  • 把同一批目标 URL 分別放在“纯 HTML 入口頁”和“JS 渲染入口頁”上做小范围對照,观察两邊被訪問的時間差。
  • 如果長期只有入口頁被抓、目标 URL 毫無動静,優先去查入口頁源碼里到底有没有那些地址。
入口頁的價值在于让搜尋蜘蛛“一眼看到”目标 URL。任何需要先执行脚本才能看到地址的寫法,都是在把這份确定性換成不确定性。

總结一下:JS 渲染不是完全没戏,但它把發現從确定變成概率事件,且不受站点控制。如果做的是 URL 發現和站点运营,入口頁優先保證原始响應里就有可抓取的連結,把脚本放在增强体驗的位置,而不是發現鏈路的第一环。