Python 实战:统计 Nginx 访问日志里的高频 IP 并生成报表

举报
辣椒酱来了 发表于 2026/10/20 11:13:16 2026/10/20
【摘要】 一、需求背景服务器跑了一段时间后,经常会遇到这些问题:到底是哪些 IP 在访问?有没有异常的高频请求?某个接口的调用来源集中在哪?Nginx 的访问日志里其实什么都有,只是直接翻文本效率太低。与其一行行看,不如写个小脚本自动统计。这次就用 Python 实现一个简单的日志分析工具。 二、日志长什么样Nginx 默认的访问日志格式大概是这样的:127.0.0.1 - - [19/Oct/20...

一、需求背景

服务器跑了一段时间后,经常会遇到这些问题:到底是哪些 IP 在访问?有没有异常的高频请求?某个接口的调用来源集中在哪?

Nginx 的访问日志里其实什么都有,只是直接翻文本效率太低。与其一行行看,不如写个小脚本自动统计。这次就用 Python 实现一个简单的日志分析工具。

二、日志长什么样

Nginx 默认的访问日志格式大概是这样的:

127.0.0.1 - - [19/Oct/2026:10:00:00 +0800] "GET /index.html HTTP/1.1" 200 612 "-" "Mozilla/5.0"

一行日志包含客户端 IP、时间、请求方法、路径、状态码、响应大小、UA 等信息。本文只提取第一列的 IP 做统计,其他字段可以按需扩展。

三、脚本设计思路

整体逻辑很简单:

  1. 逐行读取日志文件;
  2. 用正则提取每行开头的 IP 地址;
  3. 用字典累计每个 IP 出现的次数;
  4. 按次数排序,取前 N 名;
  5. 输出到控制台并导出 CSV。

这种"读取—处理—统计—输出"的流程,是日志分析的通用套路,换成分析 URL、状态码、User-Agent 也一样适用。

四、完整代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse
import csv
import re
from collections import Counter

IP_PATTERN = re.compile(r'^(\d{1,3}(?:\.\d{1,3}){3})')


def count_ips(log_path):
    counter = Counter()
    with open(log_path, 'r', encoding='utf-8', errors='ignore') as f:
        for line in f:
            match = IP_PATTERN.match(line)
            if match:
                counter[match.group(1)] += 1
    return counter


def export_csv(counter, output_path, top_n):
    with open(output_path, 'w', newline='', encoding='utf-8-sig') as f:
        writer = csv.writer(f)
        writer.writerow(['rank', 'ip', 'count'])
        for index, (ip, count) in enumerate(counter.most_common(top_n), start=1):
            writer.writerow([index, ip, count])


def main():
    parser = argparse.ArgumentParser(description='统计 Nginx 访问日志中的高频 IP')
    parser.add_argument('logfile', help='日志文件路径,例如 /var/log/nginx/access.log')
    parser.add_argument('--top', type=int, default=20, help='输出前 N 名,默认 20')
    parser.add_argument('--output', default='ip_report.csv', help='CSV 输出路径')
    args = parser.parse_args()

    counter = count_ips(args.logfile)
    total = sum(counter.values())

    print(f'共解析 {total} 条记录,涉及 {len(counter)} 个 IP\n')
    print(f'{"排名":<6}{"IP":<18}{"访问次数":<10}')
    for index, (ip, count) in enumerate(counter.most_common(args.top), start=1):
        print(f'{index:<8}{ip:<20}{count:<10}')

    export_csv(counter, args.output, args.top)
    print(f'\n报表已导出到 {args.output}')


if __name__ == '__main__':
    main()

五、运行效果

python3 ip_report.py /var/log/nginx/access.log --top 10

输出大致如下:

共解析 128340 条记录,涉及 4213 个 IP

排名    IP                 访问次数
1       192.168.1.10       8021
2       203.0.113.25       5170
3       198.51.100.7       3324
...

报表已导出到 ip_report.csv

导出的 CSV 可以直接用 Excel 打开,或者丢给图表工具做可视化。

六、进阶:定时统计

如果希望每天自动生成报表,可以配合 crontab:

0 2 * * * cd /opt/scripts && python3 ip_report.py /var/log/nginx/access.log --top 20 >> ip_report.log 2>&1

建议把报表文件按日期命名,避免被覆盖,例如改成 ip_report_20261019.csv。

七、注意事项

  • 日志文件可能被 logrotate 切分,统计前最好先确认当天的文件范围;
  • 如果启用了 IPv6,日志第一列可能是 ::1 之类的地址,需要调整正则;
  • 日志属于用户访问数据,导出和分享前注意脱敏;
  • 数据量特别大时,可以考虑按行流式处理并定期落盘,避免占满内存。

小结

本文用不到百行代码实现了一个日志统计小工具,核心思路就是"正则提取 + 字典计数 + 排序输出"。掌握了这个套路之后,统计 URL、状态码、UA 都是同样的写法。

工具本身不复杂,但日常排障时确实省事。如果你也经常和服务器日志打交道,不妨把它改成适合自己业务的版本。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。