入口页里放一条链接,目标地址却不是直接返回 200,而是先 301 到 A,A 再 302 到 B,最后才落到真正的内容页。这种结构在蜘蛛池和站点运营里很常见,通常不会让抓取彻底失败,但会让“发现”这件事变得不那么干脆。
搜索蜘蛛遇到跳转时的一般处理
搜索蜘蛛请求一个 URL 时,如果拿到的响应码是 3xx,它会读取响应头里的 Location,然后对新地址再发一次请求。这个过程会重复,直到拿到 200、404、403 这类最终响应,或者触及引擎内部的跳转次数上限后停止跟随。
有几点值得先记住:
- 跳转次数的上限各引擎都不公开,普遍认为在 5 跳左右,超过就容易被放弃;
- 爬虫一般不会把链条中间每一跳都当成独立页面收录,最终地址才是它真正要评估的对象;
- 相对路径的 Location 会按当前 URL 解析,如果中间发生域名切换,容易解析到意料之外的地址;
- 只要某一跳返回 4xx 或 5xx,链条就断在那里,后面的地址不会被请求。
301 和 302 的差别有多大
从“能不能被发现”这个角度看,两者都会被跟随,差别更多体现在信号归属和后续行为上。301 通常被视为永久迁移,引擎倾向于把原先指向跳转起点的信号归到终点;302 被视为临时,虽然也会跟,但引擎会保留原来的记录,并可能持续回来检查起点是否恢复。对运营来说,如果迁移是确定的,用 301;如果只是临时切换或 A/B 测试,用 302,但要知道它不会帮你把起点上的历史记录清理干净。
对 URL 发现的实际影响
入口页上那条链接本身仍然是有效的发现信号,蜘蛛确实会因为点击它而开始一次请求。真正被影响的是后续成本:从“入口页到目标地址”变成“入口页到跳转再到跳转再到目标地址”,多出来的每一次请求都要占用抓取配额和时间。
跳转链越长,蜘蛛在单个目标上消耗的预算越多,同一时间能覆盖的 URL 数量就越少。如果你在观察“为什么这批 URL 发现得很慢”,链路长度往往是一个容易被忽略的变量。
另外,链条中间的地址也会出现在服务器日志里,看上去像“蜘蛛在抓一个已经不用的旧页面”,其实那只是链路中的一环,不代表它对这个旧地址有额外兴趣。
日志里怎么判断蜘蛛跟了几跳
- 按时间顺序,把同一个爬虫 User-Agent 对同一批路径的请求排出来;
- 如果 /old-a 之后紧接着 /new-b,再紧接着 /final-c,状态码依次是 301、302、200,基本可以确认是一条链;
- 注意区分跳转链和独立抓取,结合 Referer 和请求间隔来看会更稳;
- 如果日志里只看到第一跳、没有后续请求,通常说明链条在某一环断了,或者跳转次数已经触到上限;
- 如果看到同一对地址反复来回出现,先怀疑循环跳转。
容易踩的几个坑
- 循环跳转:A 到 B、B 回到 A,蜘蛛会绕几圈后放弃,等于这条链接白放;
- 终点被屏蔽:终点正好落在 robots.txt 禁止的目录,前面几跳全白跑;
- 终点不是内容页:跳到登录页、验证页或错误提示页,蜘蛛拿到的并不是你希望它看到的东西;
- 跳转目标动态变化:按 UA、按 IP、按时间随机跳,日志难以复现,问题也很难定位;
- 机制混用:301 后面接 meta refresh 或 JavaScript 跳转,等于把链路拆成两套规则,可预测性更差。
更省事的做法
- 把跳转收敛成一次,直接 301 到最终地址,不要再套第二层;
- Location 尽量使用绝对地址,避免解析歧义;
- 保证终点稳定返回 200,不要时好时坏地一会儿 200 一会儿 302;
- 确认终点没有被 robots.txt 或 X-Robots-Tag 拦截;
- 蜘蛛池入口页尽量直接指向终点,而不是指向跳转的起点。
跳转链不是不能有,而是它会让发现过程多绕几圈。链路越短,蜘蛛越省事,你在日志里看到的现象也越清楚。
小结
多级跳转的核心问题不是“能不能被抓”,而是“抓得值不值”。蜘蛛会沿着 Location 一跳一跳走下去,但每多一跳就多一次请求、多一份预算消耗,也更容易在中途因为 4xx、超上限或屏蔽而中断。把入口页到目标地址的路径压到一跳,并保证终点稳定可访问,是排查这类问题时最直接、也最容易验证的做法。