不少人在做蜘蛛池入口頁时,會把連結交给 JavaScript 来輸出,理由也很實在:源碼里看不到一堆裸連結,頁面看起来干净,维護起来也方便。但這样一来,搜尋蜘蛛到底還能不能顺着這些連結走到目标 URL,就成了一個必须先弄清楚的問题。
先说结论:能,但很不稳定
搜尋蜘蛛抓取一個頁面通常分两個阶段:先是抓取初始 HTML 並解析其中的連結,然後才是渲染阶段。渲染需要額外排队,消耗的計算资源遠高于普通抓取,優先級自然更低。Google 的渲染能力相對成熟,但依然存在延迟;百度、必應等引擎對 JavaScript 渲染的支持有限,很多情况下只解析初始 HTML,脚本执行完才出現的連結就等同于不存在。
換句话说,JS 插入的連結不是绝對抓不到,而是把 URL 發現這件事從确定性操作變成了碰运气的操作。對于蜘蛛池這種依赖批量 URL 發現的做法,這一点尤其致命。
哪几種寫法風險最高
- onclick 跳轉:寫成 或者给 div、button 绑定点击事件,初始 HTML 里根本没有 href 属性,抓取阶段看不到任何可跟随的連結。
- innerHTML / document.write 插入 a 标簽:連結要等脚本执行後才進入 DOM,不渲染就等于没有。
- 前端框架路由跳轉:用 pushState 切換頁面,地址栏變了,但頁面里没有真正的 a href。
- 延迟加载連結:滚動到底部、展開更多、点击标簽頁之後才把連結插進来,需要交互触發,被抓取的概率更低。
- 接口返回資料再拼接連結:先請求 JSON,再用 JS 拼出 URL。多一层异步,多一层丢失概率。
怎么判断自己的入口頁有没有被渲染
- 看服務器日誌。把入口頁的目标 URL 單獨筛出来,如果上线後很長一段時間這些路径一條都没出現,而入口頁本身是被抓過的,基本可以判断渲染阶段没有执行到位。
- 用搜尋引擎自带的抓取測試工具,對比原始 HTML 和渲染後的 DOM,看連結是只在渲染结果里出現,還是两邊都有。
- 把浏览器 JavaScript 關掉再打開入口頁,源碼里能看到的連結才是不依赖渲染的連結。
- 統計初始 HTML 中的 a 标簽數量,和渲染完成後頁面上的連結數量做對比,差值越大,依赖 JS 的程度越高。
更稳妥的做法
如果目标是让目标 URL 被稳定發現,關键連結應当寫在初始 HTML 的 a href 里。JavaScript 可以用来做交互增强,但不适合作為連結的唯一来源。
- 服務端渲染或静態生成,把連結直接輸出到 HTML 中。
- 确實需要前端渲染时,加一层预渲染,把渲染结果直接返回给爬虫。
- 用 noscript 提供一份基础連結列表,作為兜底。
- 保留一份對爬虫可见的 sitemap,和頁面内鏈互相补充。
把 JS 渲染当成主要的 URL 發現通道,等于把抓取节奏交给了搜尋蜘蛛的渲染队列。它能做到不代表它會及时做到,更不代表每個搜尋引擎都會做到。
小结
入口頁用 JavaScript 插入連結,搜尋蜘蛛有發現目标 URL 的可能,但概率和时效都不可控。判断方法很简單:關掉 JS 看源碼里還剩多少連結。如果關键連結只在渲染後存在,就该考虑把它挪回初始 HTML,或者补上预渲染和 sitemap 這條退路。至于最终能否被收錄,仍取决于目标頁面本身的质量,這不是入口頁能替它解决的問题。