如何通过日志分析蜘蛛对网站重定向的跟随情况?
通过自定义 Nginx log_format 记录 $sent_http_location 并处理 CDN 真实 IP,再用 awk 按 301/302 状态码和爬虫 UA 过滤,串联同一 IP 的重定向请求链,可判断蜘蛛是否跟随重定向。
结论:判断蜘蛛是否跟随重定向,靠的是把 access log 里「同一个爬虫 IP 先拿到 301/302、随后又请求了 Location 指向的 URL」这条链串起来——但前提是你的日志必须记录 $sent_http_location,否则你只能看到原始 URL 返回了 301,永远看不到它跳去了哪里。
为什么默认的 access.log 判断不了重定向跟随?
结论:Nginx 默认的 combined 格式只记录请求 URL 和状态码,不记录响应头里的 Location,所以光看默认日志无法确定蜘蛛跳去了哪个地址。
Nginx 默认 combined 格式输出的是:$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"。里面没有任何响应头字段。你 grep 到一行 301,只知道「这个 URL 被永久跳转了」,跳转目标是 301 响应里的 Location: 头,而这个头根本没进日志。
怎么让 Nginx 日志记录 Location?
结论:在 http 块里自定义 log_format,加上 $sent_http_location,然后让站点的 access_log 使用这个格式。$sent_http_location 需要 Nginx 1.7.5 以上版本支持。
log_format spider '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent" '
'"$sent_http_location"';
access_log /var/log/nginx/spider.log spider;
注意两点:$sent_http_location 只在响应头确实带 Location 时才有值,普通 200 响应这一列是 "-";另外如果你用了 CDN 或反向代理,$remote_addr 拿到的是 CDN 节点 IP,需要配置 real_ip_header X-Forwarded-For 和 set_real_ip_from,否则所有蜘蛛 IP 都被改写成同一个 CDN IP,链条直接断掉。
怎么用 awk 把蜘蛛的重定向记录筛出来?
结论:用状态码 + User-Agent 两个条件过滤即可,字段位置按 combined 格式是 $9(状态码)、$12(UA,含引号需处理)。
awk '$9==301 || $9==302 {print $1, $4, $7, $9, $12}' access.log | grep -i googlebot
更进一步,做「是否跟随」的判定,思路是:对每条 301 记录,取它的 Location 值(自定义格式里是最后一个字段),在日志中查找同一 IP 在此之后是否出现过该 URL 的请求:
awk '$9==301 && tolower($12) ~ /googlebot/ {print $1"|"$7"|"$NF}' access.log
配合 sort 按 IP 和时间排序,就能肉眼或脚本化地看到跳转链。真实的 Googlebot 建议先用反向 DNS 验证身份,别只信 User-Agent(UA 可以随便伪造):
dig -x 66.249.64.1 +short # 应返回 crawl-xx-xx-xx-xx.googlebot.com
host crawl-xx-xx-xx-xx.googlebot.com # 再反查应回到原 IP
多长时间内没有后续请求,才算蜘蛛没跟随?
结论:同一个爬虫 IP 在收到 301/302 后 10 秒内请求目标 URL,基本可以判定为跟随;超过 24 小时仍未出现该 IP 对目标 URL 的请求,可判定为未跟随。
Googlebot 对服务端重定向的跟随延迟通常在几百毫秒到 3 秒之间,因为它是同一个抓取任务内完成的。把窗口放宽到 10 秒是为了容纳并发和日志时间戳精度($time_local 精确到秒,$msec 可到毫秒,需要更精细时可换成 $msec)。反过来,如果 301 的目标 URL 一直没被这个 IP 请求过,可能是三种情况:跳转链太长(超过 5 跳会被放弃)、目标 URL 被 robots.txt 屏蔽、或者目标返回了 4xx/5xx。
301 和 302 的跟随行为有什么区别?
结论:301 会被搜索引擎长期缓存,之后蜘蛛直接请求新地址、不再访问原地址;302 不缓存,蜘蛛每次仍会先请求原地址再跟随,日志里原 URL 会反复出现 302。
这带来两个分析上的实际影响:一是用 301 做跳转后,原 URL 的请求量会快速下降直到归零,这本身就是「跟随成功」的旁证;二是用 302 时,你会在日志里持续看到原 URL + 目标 URL 成对出现,统计跟随率要按「配对率」算,而不是按「原 URL 消失」算。
分析时最容易踩的三个坑
第一,JS 跳转和 meta refresh 在日志里是 200,不是 3xx,靠状态码永远筛不出来,得用 Search Console 的「网址检查→已抓取的网页」看渲染后结果。第二,同一 IP 上可能同时跑多个爬虫任务,串链时最好加上 $http_user_agent 或请求时间间隔做二次校验。第三,日志未记录 $http_referer 与 Location 时,跨域名跳转(A 站 301 到 B 站)在单一站点的日志里只能看到前半段,必须两边日志对照分析。
收束一句:把 $sent_http_location 加进日志格式,是整套分析的地基;有了它,用 awk 按 IP + 时间窗口串链,10 秒内跟到目标 URL 就算跟随成功,301 更看「原 URL 请求量下降」,302 更看「成对出现率」。
转载请注明出处,版权归原作者所有。