运营中经常会遇到这种情况:某个老 URL 被蜘蛛发现后,先 301 到一个中间地址,中间地址又 302 到另一个域名,最后才落到真正的内容页。对用户来说只是多等了一下,对蜘蛛来说,这是一条需要连续走完的路径,中间任何一步出问题,这次抓取就可能停在半路。
一次跳转,蜘蛛实际付出了什么
蜘蛛访问一个 URL 的流程是:发起请求,拿到 3xx 状态码和 Location,再对新的地址发起一次请求。每多一跳,就多一次完整的往返等待——包括连接建立、等待响应头、再读取内容。这些等待时间是叠加的,而不是并行完成的。服务器本来就不快的话,跳转链会让原本勉强能抓完的页面变成超时。
更关键的是,抓取机会是有限的。蜘蛛把预算花在跳转上,就意味着留给真正内容页的次数变少了。链条越长,末端那个页面被完整抓到的概率越低。
哪几种重定向写法最容易让路径散掉
- 链式跳转:A→B→C→D,每一跳还跨域,连接要重新建立。
- 302 当永久迁移用:蜘蛛不确定要不要更新旧地址,可能反复回来访问原 URL。
- 跳转成环:A 跳到 B,B 又跳回 A,蜘蛛跟几跳后放弃。
- 跳转终点是空壳:最终返回 200,但内容很少或为空,等于白走一趟。
- 入口地址不统一:HTTP 与 HTTPS、带 www 与不带 www、带尾斜杠与不带,互相横跳。
- Sitemap 与内链各写一套:同一批内容出现多个入口,跳转链彼此交叉。
怎么把跳转链收敛到一跳
- 先确定全站唯一的规范地址,内部链接直接指向终点,不要为了省事写成会跳转的旧地址。
- 服务器层只保留一次 301,落点直接是最终 URL,中间不再中转。
- 永久迁移用 301,临时活动或灰度页用 302,两类不要混用。
- 核对 Sitemap、canonical、内链、常见外链是否都指向同一个终点。
- 用 curl -sIL 或访问日志看实际的 Location 链,把超过一跳的逐条收敛。
- 确认终点页面返回 200 且内容完整,避免把蜘蛛引到一个空页面。
一条命令看清跳转链
在服务器或本地执行 curl -sIL -o /dev/null -w '%{url_effective} %{num_redirects}\n' https://example.com/old,可以看到跳了几次、最终落在哪个地址。批量检查时把老 URL 列表导进去逐个跑,很快就能找出那些跳了三跳以上的地址。
蜘蛛并不会因为跳转本身受到什么特别对待,问题在于每次跳转都在消耗有限的抓取机会。链条越长,真正要抓的内容越容易被排到后面。
服务器层面的配合
跳转节点最好部署在响应稳定的机器上。如果 301 是由应用层生成的,要留意上游变慢时,连 3xx 都返回不出来,蜘蛛看到的就是 5xx 或连接被重置——这时链条是从第一步就断掉的,和跳转次数无关。
抓取路径的本质,是从入口到内容的一串可预测请求。把重定向压到一跳、让所有入口指向同一个终点,能在不增加蜘蛛负担的前提下,让它更快走到你希望它看到的内容上。这件事不需要额外提交,只要把地址写对、跳转收敛,路径自然会顺。