网站蜘蛛爬虫分析教程:从日志到可视化报表。
学完这篇,你能把服务器上的 Nginx 访问日志变成一张能直接看的蜘蛛爬取报表——清楚知道百度、Google、Bing 每天来爬了多少次、爬了哪些页面、集中在什么时段。
第一步:确认日志文件路径和格式
这一步要拿到原始日志并确认格式完整,做完你能看到每条访问记录的原始长相。
SSH 登录服务器,执行:
tail -n 3 /var/log/nginx/access.log
如果输出类似:
66.249.66.1 - - [12/Mar/2025:03:21:07 +0800] "GET /article/1024 HTTP/1.1" 200 18234 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
说明是 Nginx 默认的 combined 格式(宝塔面板的日志在 /www/wwwlogs/你的域名.log)。
注意:如果站点套了 CDN,源站日志里记录的只有 CDN 节点 IP,蜘蛛痕迹在 CDN 控制台的「日志下载 / Logpush」里,别在源站上白找。
第二步:统计谁来过、各来了多少次
这一步用一条 awk 命令把 UA 字段抽出来做聚合,做完你能得到一张蜘蛛来访排行榜。
combined 格式里用双引号分割,第 6 段就是 User-Agent:
awk -F'"' '{print $6}' /var/log/nginx/access.log \
| grep -ioE 'Googlebot|Bingbot|Baiduspider|YandexBot|Bytespider|Sogou web spider|360Spider' \
| sort | uniq -c | sort -rn
输出形如 4821 Baiduspider,一眼看出谁最勤快。再统计状态码分布,判断蜘蛛有没有爬到死链:
grep -i baiduspider /var/log/nginx/access.log | awk -F'"' '{split($3,a," "); print a[1]}' | sort | uniq -c | sort -rn
注意:UA 可以随便伪造,别只看字符串。想确认是不是真 Googlebot,用
dig +short -x 66.249.66.1反查,返回googlebot.com或google.com才可信;百度蜘蛛用同样方式反查baidu.com。
第三步:看蜘蛛集中在什么时段爬
这一步按小时切片,做完你能判断抓取是否撞上网站访问高峰。
grep -i baiduspider /var/log/nginx/access.log \
| awk -F'[:[]' '{print $3":00"}' | sort | uniq -c
输出 03:00 312 这种形式,就是凌晨 3 点爬了 312 次。如果发现抓取集中在白天 10-12 点且和真实用户抢带宽,可以在百度搜索资源平台的「抓取频次」里调整。
第四步:用 GoAccess 生成可视化 HTML 报表
这一步把纯文本变成能点开的网页报表,做完你得到一个带图表、可筛选的 HTML 文件。
Ubuntu 22.04 / Debian 12 安装:
sudo apt-get install -y goaccess
先筛出蜘蛛日志,再让 GoAccess 解析(一定要带 --log-format=COMBINED,否则列会错位):
grep -iE 'Googlebot|Bingbot|Baiduspider|YandexBot|Bytespider' /var/log/nginx/access.log > /tmp/spider.log
goaccess /tmp/spider.log --log-format=COMBINED \
-o /var/www/html/spider.html \
--html-report-title="蜘蛛抓取报表"
浏览器打开 http://你的域名/spider.html,就能看到访问趋势、请求文件、状态码、UA 排行四张图。想实时刷新,加 --real-time-html,它默认监听 7890 端口。
注意:GoAccess 默认会过滤蜘蛛,这里我们主动喂给它蜘蛛日志就够了,不要再加
--ignore-crawlers;另外报表含真实 URL,放在公网目录记得加 Nginx 的auth_basic保护。
第五步:用 Python 画一张趋势对比图
这一步把多个蜘蛛的逐小时抓取量画成折线图,做完你能直观看到各家的爬取节奏差异。
import re, pandas as pd, matplotlib.pyplot as plt
pat = re.compile(r'(?P<ip>\S+).*\[(?P<t>[^\]]+)\] "(?P<req>[^"]*)" (?P<st>\d{3}) \S+ "[^"]*" "(?P<ua>[^"]*)"')
rows = [m.groupdict() for line in open('/var/log/nginx/access.log', errors='ignore')
if (m := pat.match(line))]
df = pd.DataFrame(rows)
df['t'] = pd.to_datetime(df['t'], format='%d/%b/%Y:%H:%M:%S %z')
df['bot'] = df['ua'].str.extract(r'(Googlebot|Bingbot|Baiduspider|Bytespider)')
df = df.dropna(subset=['bot'])
pivot = df.set_index('t').groupby('bot').resample('1h').size().unstack(0).fillna(0)
pivot.plot(figsize=(12, 5), title='Hourly Crawl Trend')
plt.tight_layout(); plt.savefig('/tmp/spider_trend.png', dpi=120)
注意:matplotlib 默认不含中文字体,图表标题请用英文,或先执行
plt.rcParams['font.sans-serif']=['Noto Sans CJK SC']。
第六步:挂上定时任务
这一步让报表每天自动更新,做完你早上打开链接就是最新数据。
执行 crontab -e,追加一行:
0 4 * * * grep -iE 'Googlebot|Bingbot|Baiduspider|Bytespider' /var/log/nginx/access.log > /tmp/spider.log && /usr/bin/goaccess /tmp/spider.log --log-format=COMBINED -o /var/www/html/spider.html
注意:日志被 logrotate 切割后,历史记录会轮转到
.1、.2.gz。想统计整周数据,用zcat /var/log/nginx/access.log.*.gz配合当前日志一起拼接。
小结
- 日志路径
/var/log/nginx/access.log,宝塔在/www/wwwlogs/; - UA 取 combined 格式第 6 段,状态码在第 3 段的第一个数字;
- GoAccess 必须显式指定
--log-format=COMBINED,否则字段全错; - 判断真假蜘蛛靠 IP 反向解析,不能只看 UA 字符串;
- CDN 站点要到 CDN 日志里找蜘蛛记录,源站日志会被节点 IP 覆盖;
- 定时任务要处理 logrotate 切割,用
zcat补历史数据。
原文链接:https://www.gj0.com/thread-1434.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。