Phpstudy博客网站Apache2日志分析Python代码实现

Apache2日志文件记录了服务器访问、错误等信息,通过Python分析这些日志可以获取用户行为、流量统计等关键数据。以下是基于Python实现Apache2日志分析的完整方案。

日志文件格式解析

Apache2默认日志格式为Combined Log Format,每行记录包含客户端IP、访问时间、请求方法、资源路径、状态码等信息。典型日志条目如下:

192.168.1.1 - - [10/Oct/2023:14:32:01 +0800] "GET /index.php HTTP/1.1" 200 1234 "http://example.com" "Mozilla/5.0"

使用正则表达式匹配日志条目:

import re

log_pattern = r'(\d+\.\d+\.\d+\.\d+) - - \[(.*?)\] "(.*?)" (\d+) (\d+) "(.*?)" "(.*?)"'
compiled_pattern = re.compile(log_pattern)

日志解析与数据提取

定义日志解析函数处理原始日志文件:

def parse_log_file(log_path):
    log_data = []
    with open(log_path, 'r') as f:
        for line in f:
            match = compiled_pattern.match(line)
            if match:
                ip = match.group(1)
                timestamp = match.group(2)
                request = match.group(3)
                status = match.group(4)
                size = match.group(5)
                referrer = match.group(6)
                user_agent = match.group(7)
                
                log_data.append({
                    'ip': ip,
                    'timestamp': timestamp,
                    'request': request,
                    'status': status,
                    'size': int(size),
                    'referrer': referrer,
                    'user_agent': user_agent
                })
    return log_data

常用分析维度实现

访问IP统计:

from collections import Counter

def analyze_ips(log_data):
    ip_list = [entry['ip'] for entry in log_data]
    ip_counts = Counter(ip_list)
    return ip_counts.most_common(10)

HTTP状态码分析:

def analyze_status_codes(log_data):
    status_list = [entry['status'] for entry in log_data]
    status_counts = Counter(status_list)
    return dict(status_counts)

流量统计:

def analyze_traffic(log_data):
    total_size = sum(entry['size'] for entry in log_data)
    avg_size = total_size / len(log_data) if log_data else 0
    return {
        'total_bytes': total_size,
        'average_bytes': avg_size
    }

可视化分析结果

使用Matplotlib生成可视化图表:

import matplotlib.pyplot as plt

def plot_status_distribution(status_data):
    labels = status_data.keys()
    values = status_data.values()
    
    plt.figure(figsize=(10, 6))
    plt.bar(labels, values)
    plt.title('HTTP Status Code Distribution')
    plt.xlabel('Status Code')
    plt.ylabel('Count')
    plt.savefig('status_distribution.png')
    plt.close()

完整处理流程示例

if __name__ == "__main__":
    # 日志文件路径
    log_file = '/var/log/apache2/access.log'
    
    # 解析日志
    logs = parse_log_file(log_file)
    
    # 执行分析
    top_ips = analyze_ips(logs)
    status_codes = analyze_status_codes(logs)
    traffic_stats = analyze_traffic(logs)
    
    # 输出结果
    print(f"Top 10 IPs: {top_ips}")
    print(f"Status Codes: {status_codes}")
    print(f"Traffic Stats: {traffic_stats}")
    
    # 生成可视化
    plot_status_distribution(status_codes)

进阶分析功能

异常访问检测:

def detect_abnormal_access(log_data, threshold=100):
    ip_counts = Counter([entry['ip'] for entry in log_data])
    return [ip for ip, count in ip_counts.items() if count > threshold]

热门页面分析:

def analyze_popular_pages(log_data, top_n=5):
    requests = [entry['request'].split()[1] for entry in log_data]
    return Counter(requests).most_common(top_n)

日志轮转处理方案

处理经过logrotate轮转的日志文件:

import gzip

def parse_rotated_logs(base_path):
    logs = []
    for i in range(1, 6):  # 假设保留5个历史日志
        log_path = f"{base_path}.{i}"
        if os.path.exists(log_path):
            if log_path.endswith('.gz'):
                with gzip.open(log_path, 'rt') as f:
                    logs.extend(parse_log_lines(f))
            else:
                with open(log_path, 'r') as f:
                    logs.extend(parse_log_lines(f))
    return logs

性能优化建议

处理大型日志文件时考虑以下优化措施:

  • 使用生成器逐行处理而非一次性加载全部内容
  • 对正则表达式进行预编译
  • 采用多进程处理历史日志文件
  • 使用Pandas进行数据分析时可指定数据类型减少内存占用

日志分析应用场景

该方案适用于:

  • 识别恶意扫描和攻击行为
  • 分析用户访问模式和热门内容
  • 监控服务器性能瓶颈
  • 统计流量消耗和带宽使用情况
  • 优化网站结构和内容布局

以上代码提供了完整的Apache2日志分析实现,可根据实际需求调整分析维度和输出格式。对于生产环境部署,建议添加日志监控和自动化报告生成功能。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐