做蜘蛛池的人经常問一個問题:入口頁的連結是用 JavaScript 動態插入的,搜尋蜘蛛到底看不看得见?答案不是简單的“能”或“不能”,而是取决于蜘蛛走到哪一步,以及你有没有留退路。
搜尋蜘蛛處理 JavaScript 的两個阶段
主流搜尋引擎的抓取流程大致可以拆成两段:先按 URL 抓取一次服務器返回的原始 HTML,把這批内容交给後面的處理队列;如果頁面里有脚本,再由渲染队列去执行 JavaScript,拿到渲染後的 DOM。两段之間有間隔,間隔可能是几小时,也可能是几天。
關键在于,URL 發現靠的是連結,而連結必须出現在蜘蛛目前能看到的那份内容里。如果目标 URL 只存在于 JS 执行之後才生成的 DOM 中,那么第一次抓取时,蜘蛛手里就是一份没有這條連結的頁面。
几種常见寫法,结果差別很大
- 服務端直出的 a 标簽:原始 HTML 里就有 href,第一次抓取就能發現,最稳。
- JS 動態插入的 a 标簽:要等渲染阶段才可见,發現時間被推迟,而渲染是有配額的,URL 一多容易被排到很後面。
- onclick 跳轉或前端路由跳轉:源碼里可能只有一串參數或一個 data 属性,没被渲染时基本等于不存在。
- 点击後才加载的列表:比如“展開更多”“下一頁”由 JS 触發,如果蜘蛛不触發点击,後面的連結就一直不出現。
怎么自查入口頁是否“可被發現”
- 用 curl,或者在浏览器里禁用 JavaScript,直接看返回的源碼,搜一下有没有目标 URL 的 href。
- 查服務器日誌,看蜘蛛是否抓取了頁面依赖的 JS 文件。如果连 JS 都没抓,渲染這一步大概率没發生。
- 對比“抓取時間”和“渲染後連結出現的時間”,如果差得很离谱,說明發現依赖渲染队列。
- 用搜尋引擎自带的抓取測試類工具,看它展示的渲染结果里有没有你的連結。
必须用 JS 时,怎么把损失降到最低
- 把入口頁最關键的連結放在服務端渲染的静態列表里,JS 只负责样式和交互。
- 首屏不要依赖接口返回,先把連結寫進 HTML,再去补資料。
- 避免把連結藏在下拉菜單、Tab、懒加载模块里,蜘蛛不會主動去点。
- 頁面數量多的时候,给一個静態的索引頁或分頁结构,別全靠無限滚動。
- noscript 里放一份連結可以作為兜底,但不要指望它能替代正常渲染。
渲染不是“不做”,而是“排队做”。入口頁越多、JS 越重,這條队列就越長,URL 發現的延迟也就越明顯。
一個容易忽略的细节
有些站点入口頁本身是静態的,但連結指向的目标 URL 用了前端路由,服務器對任意路径都返回同一個壳頁面。這種情况下蜘蛛抓到的内容高度相似,即使發現了 URL,後續處理也容易卡住。入口頁和落地頁尽量保留一份能被直接讀取的 HTML,是更省事的做法。
總结一句:搜尋蜘蛛能不能發現你的目标 URL,不取决于它“支不支持 JavaScript”,而取决于連結是不是出現在它第一次就能拿到的那份内容里。能用静態連結就用静態連結;用不了的时候,也要给渲染留一條清晰的路径。