常见問题

入口頁的目标連結由 JavaScript 動態渲染,搜尋蜘蛛還能發現吗?

入口頁上的目标連結如果由 JavaScript 動態插入,搜尋蜘蛛是否還能發現?本文說明搜尋引擎抓取與渲染的两步流程、容易被漏掉的几種寫法、可落地的改進做法,以及用日誌驗證渲染抓取有没有真正發生的方法,帮助站点运营排查 URL 發現环节的問题。

常见問题

入口頁的目标連結由 JavaScript 動態渲染,搜尋蜘蛛還能發現吗?

入口頁上放目标連結,是蜘蛛池里最常见的操作之一。現在不少入口頁是用前端框架或者一段脚本拼出来的,連結在浏览器里看得见,但服務器返回的原始 HTML 里找不到。這種情况下,搜尋蜘蛛能不能發現目标 URL,答案不是简單的能或不能,而是取决于連結出現在哪個环节。

先確認一件事:連結在不在初始 HTML 里

用浏览器打開入口頁,右键查看網頁源代碼(注意不是“检查元素”)。如果在源代碼里搜不到目标 URL,那這條連結就属于需要执行 JavaScript 才會出現的類型。搜尋引擎處理這類連結的方式,和普通 HTML 連結並不一样。

搜尋蜘蛛處理 JavaScript 的基本流程

主流搜尋引擎通常分两步走:先抓取服務器返回的 HTML,把頁面放進渲染队列;之後再安排一次带渲染能力的抓取,执行頁面上的脚本,拿到渲染後的 DOM,再從里面提取連結。

也就是说,JS 渲染出来的連結是有机會被發現的,但要穿過更多环节:渲染队列可能积压、脚本可能报错、外部资源可能加载失敗或超时、渲染结果可能不完整。任何一個环节出問题,這條連結在那一轮抓取里就不會被發現。

容易被漏掉的几種寫法

  • 用 innerHTML 拼接字符串插入連結,或者在脚本里用 document.write 輸出連結
  • 連結要等某個接口返回資料之後才插入,接口慢或失敗时頁面上什么都没有
  • 需要用戶点击“展開更多”“加载更多”才會出現
  • 用 onclick 加 location.href 跳轉,而不是标准的 a 标簽加 href 属性
  • 設定了較長的延时(比如几秒後才插入),渲染抓取的等待窗口可能等不到
  • 内容依赖登入狀態、cookie 或者特定地区判断,抓取时拿不到同样结果

想让目标 URL 更容易被發現,可以這样做

  1. 把最關键的目标連結放在服務端渲染的 HTML 里,脚本只负责附加内容
  2. 用标准 a 标簽加 href,不要用按钮或 div 模拟連結
  3. 如果确實要异步插入,尽量缩短等待時間,不要依赖用戶交互触發
  4. 保證接口和静態资源可正常訪問,別让渲染過程因為某個资源返回 4xx、5xx 而中断
  5. 在入口頁保留一份纯 HTML 的兜底連結列表,脚本加载失敗时仍有連結可抓

怎么驗證連結有没有被渲染到

  • 關閉浏览器 JavaScript 再看頁面,如果連結全部消失,說明嚴重依赖渲染
  • 看服務器日誌里有没有带渲染特征的抓取請求,以及脚本、接口等渲染资源是否被請求過
  • 對比原始 HTML 抓取和渲染抓取的時間,看渲染抓取是不是经常缺失或失敗
  • 检查渲染相關請求有没有大量 429、超时,這通常意味着抓取预算被浪費掉了
JS 渲染只代表“有机會被發現”,不代表一定被發現,更不代表會被收錄或获得排名。入口頁本身的可訪問性、稳定性和内容质量,仍然是更基础的前提。

常见的几個誤区

  • 以為“浏览器能看到,搜尋蜘蛛就能看到”,但浏览器和爬虫的执行环境並不等價
  • 以為渲染抓取是無限次的,實际上渲染消耗资源,频率和配額都有限
  • 以為單頁應用不需要任何處理,如果路由用 history API 又没有服務端兜底,連結往往更难被發現
  • 把所有連結都交给脚本生成,原始 HTML 里空無一物,抓取预算花在渲染上却没換来 URL 發現

小结

如果入口頁的目标連結必须由 JavaScript 才能出現,處理思路其實很直接:能放回 HTML 的就放回 HTML;放不回去的,缩短渲染依赖鏈、减少外部资源阻塞、保留兜底連結,然後用日誌確認渲染抓取到底有没有發生。發現只是第一步,之後的抓取和收錄,還要看目标頁面自身的情况。