不少人在做蜘蛛池入口页时,会把链接交给 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 这条退路。至于最终能否被收录,仍取决于目标页面本身的质量,这不是入口页能替它解决的问题。