为什么跳转方式值得单独说清楚
入口页本身通常不是最终想让蜘蛛看到的内容,它更像一个中转站:蜘蛛爬到这里,需要顺着一次跳转走到目标页。这次跳转发生在服务器层还是 HTML 层、是 301 还是 JS,直接决定了蜘蛛会不会跟、跟到哪一步、以及入口页自己会不会被留下索引。
很多入口页铺得没问题,URL 也提交了,日志里能看到抓取记录,但目标页始终没有动静,问题往往就出在这一跳上。
四种跳转方式在蜘蛛眼里的差别
301 永久重定向
服务器直接返回状态码和 Location 头,不依赖渲染,也不依赖页面内容。蜘蛛拿到的第一条响应就明确告诉它:旧地址永久作废,请去新地址。这是最稳的一种,信号集中、路径最短。
需要注意的是别把 301 做成链条。A 跳 B、B 又跳 C,每多一跳,蜘蛛就要多等待一次响应,中途放弃的概率上升,传递过去的信号也会被折损。尽量一跳到位。
302 临时重定向
语义是临时。爬虫一般也会跟随,但它倾向于保留原 URL,认为原来的地址还会回来。长期用 302 做入口跳转,可能出现入口页被收录、目标页反而没被认定为最终地址的情况。
如果入口页本来就是消耗品,被收录也无所谓,那 302 用起来没什么心理负担;如果希望目标页被当成正主,长期 302 就不是好选择。反过来,入口页需要轮换目标页时,302 的临时语义反而更贴合实际。
meta refresh
写在 HTML 的 head 里,服务器返回的是 200,蜘蛛先拿到的是入口页本身的 HTML,然后才需要解析这行声明才能发现下一站。有的爬虫会跟随,有的只把它当作普通页面,延迟设为 0 也不保证被识别成重定向。
它的价值在于不依赖服务器配置,静态托管、CDN 规则改不动的场景下能顶上,但结果带着不确定性,适合当兜底而不是首选。
JavaScript 跳转
通过脚本修改地址,需要执行 JS 才会发生。爬虫的渲染能力有限,很多情况下根本不执行,或者执行了也已经过了它判断内容的时机。结果是入口页被抓了,目标页一次没到。
如果确实只能用 JS,至少在不能被脚本覆盖的区域放一条普通的可点链接,让不执行 JS 的抓取也能有路可走。同时注意入口页 HTML 里别只剩占位内容,容易被当成空页处理。
怎么选:按目的倒推
- 目标页是最终落点、入口页不打算被收录:用 301,一跳到位。
- 目标页还在调整、可能随时更换:可以用 302,接受入口页被收录的可能。
- 改不了服务器响应头,也不跑 JS:用 meta refresh,接受不确定性。
- 只想统计入口页有没有被访问:用服务器日志或埋点,不必为此加跳转。
几个反复出现的坑
- 大量入口页 301 到同一个目标页,蜘蛛跟几次之后就不再跟了。
- 跳转链过长,或者两个地址互相跳形成循环。
- 跳转之后落到 404、403,或者需要登录才能看的页面。
- 目标 URL 每次带上随机参数,蜘蛛每次看到的都是新地址。
- 入口页内容和目标页主题完全不搭,跳过去也留不住。
上线前可以做的自查
- 用命令行工具只看响应头,确认返回的真实状态码,而不是浏览器渲染后的结果。
- 数一下跳转链长度,超过一跳就考虑合并。
- 用不执行 JS 的方式取一次入口页,看能不能顺着页面里的链接走到目标页。
- 翻一段时间日志,看入口页的返回码分布,是否出现大量 302 或 200 而没有后续请求。
- 确认目标页可正常访问,不是错误页,也没有访问限制。
跳转不是越多越自然。一次干净、方向明确的 301,通常比几层叠起来的临时跳转更容易被蜘蛛理解。