⭐ 推荐:社区规则条款 V1.0

如何用 awk 命令快速统计蜘蛛抓取日志?

juming
juming 初级会员超兽战士
发布于 2026-10-12 08:32 ·1 浏览 ·3 回复
内容摘要

介绍用 awk 从 Nginx 日志统计百度、Google、必应等蜘蛛的抓取总量、状态码分布与每小时频次,需按双引号切分提取完整 UA 并用 tolower 兼容不同 awk,无需额外分析工具。

版权声明:本文来自 GJ站长论坛《如何用 awk 命令快速统计蜘蛛抓取日志?》
原文链接:https://www.gj0.com/thread-1709.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 3

liulian
liulian 初级会员超兽战士 1楼 2026-10-12 08:34

思路是对的,-F'"' 取 $6 拿完整 UA 也没问题;但第四步的时段统计别在 -F'"' 里硬拆时间,换回默认分隔符更干净。

combined 格式按空格切时 $4 是 [12/Mar/2024:10:23:45,从第 14 个字符取 2 位就是小时,蜘蛛匹配直接对整行做小写后匹配即可:

awk 'tolower($0) ~ /baiduspider/ {print substr($4,14,2)}' access.log | sort | uniq -c | sort -k2

这样比在 -F'"' 下再从 $1 里二次拆时间稳得多,也避开了 UA 带空格的老问题。

另外建议把总量、状态码、时段做成单次 awk 遍历,用数组在 END 里输出,几 GB 的日志读一遍就够了,别反复扫同一个文件:

awk '{ua=tolower($0); h=substr($4,14,2)
  if (ua ~ /baiduspider/) {c++; st[$9]++; hr[h]++}}
END{for(k in st) print "状态", k, st[k]; for(k in hr) print "时段", k, hr[k]}' access.log

坑有两个:一是日志被 logrotate 压成 .gz 后 awk 读不了,得用 zcat access.log.*.gz | awk ...;二是 UA 可以随便伪造,只看 UA 统计出来的“百度蜘蛛”里常混着采集器,要坐实身份还得反查 IP(Googlebot 官方 JSON 段、百度也有公开 IP 列表)。顺带一提,Bytespider 抓取量往往大得离谱且不带来流量,很多站长是直接在 Nginx 层封掉的。

域名注册
域名注册 初级会员资深会员超兽战士 👑年卡会员 #550 2楼 2026-10-12 08:36
liulian:思路是对的,`-F'"'` 取 `$6` 拿完整 UA 也没问题;但第四步的时段统计别在 `-F'"'` 里硬拆时间,换回默认分隔符更干净。 combined…

对,时段统计换回默认分隔符用 substr($4,14,2) 最干净,在 -F'"' 里二次拆时间纯属自找麻烦,而且不只是时间——-F'"' 下状态码也不在 $9 了($2 是请求行,状态码实际落在 `

周末
周末 正式会员超兽战士 #551 3楼 2026-10-12 08:39
域名注册:对,时段统计换回默认分隔符用 `substr($4,14,2)` 最干净,在 `-F'"'` 里二次拆时间纯属自找麻烦,而且不只是时间——`-F'"'` 下状态…

对,你后半句被截断了,补全就是:在 -F'"' 下,状态码和响应字节数一起落在 $3(形如 " 200 5321 "),$2 是整行请求,$4 是 referer,$5 是那个夹在引号之间的空格,$6 才是完整 UA。成对的双引号把字段切开后,这套映射和默认空格切分完全不是一回事,所以谁要是在 -F'"' 里还去取 $9,拿到的就是字节数或者干脆是空。

真要取状态码得再切一刀,注意 $3 开头带一个空格,直接 split 会多冒出一个空字段:

awk -F'"' 'tolower($6) ~ /baiduspider/ {split($3,a," "); print a[2]}' access.log

更偷懒的是写 $3+0,awk 做数字转换时会自动跳过前导空白、读到非数字为止,结果正好是 200,字节数则用 a[3]。

其实换个角度更清楚:如果一条命令里只做蜘蛛识别、状态码和时段统计,那压根不需要 -F'"',默认空格切分配 tolower($0) 整行匹配就够了;-F'"' 的唯一价值是拿完整 UA 去做聚合或原样输出。两种模式混在一条管道里,是最容易出错的写法,建议一条管道只选一种。

顺带一提,有些 Nginx 配置里 referer 为 "-"、UA 为空时是 "",$6 可能压根不存在,匹配前加个 if ($6 != "") 判空会更稳。