蜘蛛池常见的结构是:入口页负责被发现,目标 URL 才是真正想被访问的地址。有些方案会在两者之间加一层跳转,比如入口页先跳到中间地址,再落到目标页。这一层跳转对搜索蜘蛛来说并不透明,处理方式和直链有明显区别。
不同跳转形式,搜索蜘蛛的处理并不一样
301 与 302
301 表示永久移动,302 表示临时移动。搜索蜘蛛一般都会跟随这两种跳转,把抓取结果落到跳转后的地址上。区别更多体现在后续判断:301 通常被视为地址已经固定,之后从原地址进入的频率可能下降;302 保留了原地址,蜘蛛仍可能反复从原地址进入。如果入口页本身就是临时的分发入口,用 302 更符合语义;如果是确定不再使用的旧地址,用 301 更合适。
容易被忽略的一点是,跳转链越长,蜘蛛在每一跳上花的时间越多。A 到 B 再到 C 这种两跳结构,比 A 直达 C 多一次请求,在入口页数量较大的场景下,这个成本会被放大。
meta refresh 与 JavaScript 跳转
meta refresh 属于 HTML 层的跳转,蜘蛛通常能识别,但延迟时间为 0 和延迟几秒的处理结果不完全一样。延迟过长的写法有时会被当成页面内容的一部分,而不是跳转指令。
JavaScript 跳转依赖脚本执行。具备渲染能力的抓取程序可能跟到目标地址,但这个环节并不保证一定发生,尤其是在页面脚本较多、外部资源加载超时的情况下。把跳转逻辑放在 JS 里,等于把能否被发现交给了一个不确定环节。
跳转过程中值得留意的几个细节
- robots.txt:每一跳的地址各自受其所在域名的 robots.txt 约束。入口页放行、中间地址被禁止,链条就可能断在中间。
- nofollow 与 meta robots:响应头或页面里的 noindex、nofollow 一般不阻止蜘蛛跟随跳转,但会影响它对后续地址的判断,不适合拿来当抓取开关。
- 依赖 UA 或 Cookie 的分流:部分入口页会对不同 UA 返回不同的跳转目标。蜘蛛拿到的结果和你浏览器里看到的不一致时,日志和实际效果就对不上。
- 并发与超时:跳转链中任何一跳响应慢或超时,整条链路都不会走完。
从日志确认跳转有没有被走通
如果日志里能看到蜘蛛访问入口页的记录,却看不到目标 URL 的请求记录,可以按下面几项核对:
- 入口页返回的状态码是 200 还是 3xx,跳转目标是否和预期一致。
- 中间地址是否也出现在日志里,有没有被请求过。
- 中间地址所在域名的 robots.txt 是否放行。
- 跳转是服务端下发还是页面脚本触发,前者在日志里一定有迹可循。
抓取日志只能说明蜘蛛来过,不代表它跟着你的预期走到了终点。跳转链上的每一跳都会留下自己的记录,缺了哪一环就去查哪一环。
更稳妥的做法
能直链就直链。入口页到目标 URL 的跳转,每多一层就多一份不确定性。如果确实需要中间层来做统计或分流,可以参考以下几点:
- 用 301 或 302 完成跳转,不要依赖 JavaScript。
- 把跳转层数控制在一层以内。
- 中间地址保持可抓取,状态码稳定,不要时好时坏。
- 避免用 UA 判断给蜘蛛和普通用户返回不同的跳转目标。
跳转本身不是问题,问题在于链路中任何一个环节都可能出状况,而排查时往往只看了入口页和最终页两端。把中间环节也纳入观察范围,很多“蜘蛛来过却没有后续”的情况就有了解释。