全面的Pandas数据处理参考手册:从数据清洗、时间序列分析到网络日志解析

July 16, 2026

全面的Pandas数据处理参考手册:从数据清洗、时间序列分析到网络日志解析

Pandas作为Python数据分析的核心库,提供了丰富的数据处理工具。以下我将为您梳理一份全面的Pandas数据分析代码示例与最佳实践指南,覆盖您提到的多个核心应用领域。

一、用户行为日志分析

处理日志数据通常涉及时间序列解析、会话划分和多维度统计。

import pandas as pd
import numpy as np

解析时间戳,设置索引

df['timestamp'] = pd.to_datetime(df['timestamp'], format='%Y-%m-%d %H:%M:%S') df.set_index('timestamp', inplace=True)

按小时统计活跃用户

hourly_active = df['user_id'].resample('H').nunique()

会话分割(假设30分钟无活动为新会话)

df['session_id'] = (df['timestamp'].diff() > pd.Timedelta(minutes=30)).cumsum()

漏斗分析(多步转化)

funnel_steps = ['view', 'add_cart', 'purchase'] funnel_data = df[df['event'].isin(funnel_steps)].groupby('user_id')['event'].apply(list)

计算转化率

total_view = (funnel_data.apply(lambda x: 'view' in x)).sum() total_purchase = (funnel_data.apply(lambda x: 'purchase' in x)).sum() conversion_rate = total_purchase / total_view

二、实验数据处理最佳实践

1. 加载时指定数据类型节省内存

dtype_dict = {'user_id': 'int32', 'score': 'float32', 'group': 'category'} df = pd.read_csv('experiment_data.csv', dtype=dtype_dict)

2. 处理缺失值(多重策略)

删除法

df_clean = df.dropna(subset=['key_column'])

填充法

df['value'] = df['value'].fillna(df.groupby('group')['value'].transform('median'))

插值法

df['value'] = df['value'].interpolate(method='linear')

3. 异常值处理(IQR法则)

Q1 = df['metric'].quantile(0.25) Q3 = df['metric'].quantile(0.75) IQR = Q3 - Q1 df_filtered = df[(df['metric'] >= Q1 - 1.5*IQR) & (df['metric'] = price_q1) & (df['price']

异常值缩尾处理(Winsorization)

from scipy.stats.mstats import winsorize df['value'] = winsorize(df['value'], limits=[0.05, 0.05])

2. 综合案例:电商数据清洗全流程

  • 流程覆盖:加载→缺失值处理→异常值检测→格式规范→特征工程→分析保存。
  • 代码亮点
    • 使用业务逻辑填充(如按类别填充价格)
    • 结合分组与条件逻辑进行清洗
    • 保存为高效格式(Parquet)
  • 输出物:清洗后的数据集、统计分析结果、可视化图表。

二、数据分析与聚合

3. 销售数据分析(groupby / pivot_table)

  • 选择策略
    • groupby:灵活分组、复杂计算链(如transformfilter)。
    • pivot_table:快速生成交叉报表,支持多级行列、汇总边距。
  • 代码对比
    # groupby:多维度聚合
    sales_by_category = df.groupby(['category', 'month'])['revenue'].agg(['sum', 'mean']).reset_index()
    
    # pivot_table:制作报表
    pivot = pd.pivot_table(df, values='revenue', index='month', columns='category', 
                           aggfunc='sum', margins=True, fill_value=0)

4. 文本数据处理(str / 正则)

三、时间序列处理

5. 时间序列分析(resample / rolling)

滚动窗口:7日移动平均与标准差

df['rolling_mean'] = df['value'].rolling(window=7, min_periods=1).mean() df['rolling_std'] = df['value'].rolling(window=7).std()

6. 用户行为日志分析(时间序列实战)

  • 关键步骤
    1. 解析时间戳:pd.to_datetime(log_df['timestamp'])
    2. 按时间聚合:log_df.set_index('timestamp').resample('H').size()
    3. 会话分割:基于时间差(如30分钟)划分用户会话。
  • 衍生指标
    • 日均活跃用户(DAU)
    • 用户留存率(按首次访问日分组计算)

四、数据重塑与优化

7. 数据重塑(melt / pivot / stack)

  • 转换场景
    • 宽表→长表melt(多个列名转为值)
    • 长表→宽表pivot(唯一索引)或 pivot_table(支持重复值聚合)
    • 多层索引转换stack(列→行)、unstack(行→列)
  • 示例
    # melt:将多个月份列转为“月份-销售额”行
    long_df = wide_df.melt(id_vars=['city'], var_name='month', value_name='sales')
    
    # pivot:恢复为宽表
    wide_again = long_df.pivot(index='city', columns='month', values='sales')

8. 数据结构优化(dtypes / memory_usage)

10. 实验数据统计(数值型处理)

基于IQR的异常值过滤

Q1, Q3 = df['value'].quantile([0.25, 0.75]) IQR = Q3 - Q1 df_clean = df[(df['value'] >= Q1 - 1.5*IQR) & (df['value'] 重要提示:如果后续操作涉及跨时区合并或分析,必须正确处理时区。操作的核心是区分 tz_localize(为原始无时区数据声明时区)和 tz_convert(在不同时区间转换)。> # 假设原始数据是北京时间字符串,但无时区信息

df['ts'] = pd.to_datetime(df['time_str'])

1. 声明原始时区是 Asia/Shanghai

df['ts_localized'] = df['ts'].dt.tz_localize('Asia/Shanghai')

2. 统一转换为UTC(内部计算推荐)

df['ts_utc'] = df['ts_localized'].dt.tz_convert('UTC')

3. 转换为目标时区 America/New_York 用于展示

df['ts_ny'] = df['ts_utc'].dt.tz_convert('America/New_York')


**黄金法则**:必须先 `tz_localize`(声明原始时区),再 `tz_convert`

🔄 重采样(Resampling):改变观测频率

重采样用于改变时间序列的频率,本质是“按新频率分组 + 聚合”。其两个主要方向是:

  • 降采样(Downsampling):从高频到低频(如日 -> 月),需要进行聚合。
  • 升采样(Upsampling):从低频到高频(如月 -> 日),会产生缺失值,需要填充。

1. 基础降采样与聚合

resample() 返回一个 Resampler 对象,必须接聚合操作(如 .sum(), .mean())才能得到结果。

# 按日('D‘)聚合,销售额求和,访问量求平均
df_daily = df.resample('D').agg({'sales': 'sum', 'visitors': 'mean'})
# 按周汇总,指定周一为每周起始日,标签使用区间左端
weekly_sales = df['sales'].resample('W-MON', label='left').sum()
# 直接计算金融K线数据(开盘、最高、最低、收盘)
df_ohlc = df['price'].resample('D').ohlc()

2. 关键参数:closed 与 label

这两个参数控制分组边界和结果标签,错误配置会导致结果“偏移一天”。

| closed | 定义分组的哪一侧是闭合(包含)的。 | closed='right':月度分组包含当月的最后一天。 | | label | 定义使用分组的哪一侧边界作为结果的索引标签。 | label='right':结果标签显示为月末日期(如2023-01-31)。 |

财务月报场景:结果标签为月末日期

monthly_report = df.resample('M', closed='right', label='right').sum()

更清晰的写法:直接使用月末频率别名 'ME' (Month End)

monthly_report = df.resample('ME').sum()

最佳实践:使用更直观的频率别名(如 'MS' 月初,'ME' 月末,'QE' 季末)来避免混淆,代码意图更明确。

3. 升采样与缺失值填充策略

升采样会产生缺失值(NaN),必须指定填充方法。

将日数据升采样为小时数据

df_hourly = df.resample('H').asfreq() # 仅改变频率,不填充

前向填充 (Forward Fill)

df_ffilled = df.resample('H').ffill()

后向填充 (Backward Fill)

df_bfilled = df.resample('H').bfill()

线性插值(更平滑)

df_interpolated = df.resample('H').interpolate(method='linear')

填充固定值(如0),适用于计数数据

df_filled_zero = df.resample('H').sum().fillna(0)

注意:应在重采样聚合之后进行填充,例如 df.resample('D').sum().fillna(0)。

📊 滑动窗口(Rolling)与扩展窗口(Expanding)分析

rolling 和 expanding 用于计算窗口内的统计量,是平滑数据、计算移动指标和累积指标的关键。

1. 滚动窗口(rolling):分析局部趋势

rolling 在固定长度的窗口上滑动计算,适用于分析短期趋势和波动。

计算7日简单移动平均 (SMA)

df['7d_avg_sales'] = df['sales'].rolling(window=7, min_periods=1).mean()

计算20日滚动标准差(用于衡量波动率)

df['20d_std'] = df['price'].rolling(window=20).std()

基于时间的窗口:计算30天内的滚动总和(适用于不规则时间序列)

df['30d_rolling_sum'] = df['volume'].rolling(window='30D').sum()

自定义加权移动平均

weights = np.array([0.1, 0.2, 0.3, 0.4]) # 最近的数据权重最大 df['weighted_ma'] = df['value'].rolling(window=4).apply(lambda x: np.dot(x, weights))

计算两个序列的滚动相关性(例如股票与大盘)

rolling_corr = returns['stock_A'].rolling(window=60).corr(returns['market_index'])

关键参数 min_periods:定义进行计算所需的最小非空观测值数量,可有效避免结果序列前端出现过多NaN。

df['sales_trend'] = df['sales'].rolling(window=30, min_periods=5).mean() # 至少有5天数据就计算

2. 扩展窗口(expanding):计算累积统计

expanding 的窗口从序列起点开始,逐步扩展到当前点,用于计算累积量。

计算累计销售额

df['cumulative_sales'] = df['sales'].expanding().sum()

计算历史平均值(至今)

df['historical_avg'] = df['sales'].expanding().mean()

计算历史最大值

df['peak_to_date'] = df['sales'].expanding().max()

3. 高级技巧:结合分组实现周期内累积

标准的 expanding() 会跨越所有日期。若需按自然周期(如每日)重置累积计算,需结合 groupby。

计算每个交易日内的累计成交额

df['cumulative_volume_intraday'] = df.groupby(df.index.date)['volume'].expanding().sum().values

计算每个用户会话内的累计活动次数(假设已有 session_id)

df['actions_in_session'] = df.groupby('session_id')['action'].expanding().count().values

🛠️ 综合应用场景示例

场景一:电商销售分析

计算月度销售额,并生成同比环比

df['order_month'] = df['order_date'].dt.to_period('M') # 创建周期列 monthly_sales = df.groupby('order_month')['revenue'].sum()

计算环比增长率

monthly_sales_pct_change = monthly_sales.pct_change()

计算3个月移动平均,平滑季节性波动

monthly_sales_ma3 = monthly_sales.rolling(window=3, min_periods=1).mean()

场景二:用户行为日志分析

按小时统计独立活跃用户数

hourly_active_users = df['user_id'].resample('H').nunique()

计算每小时请求量的7小时移动平均,观察负载趋势

df['request_7h_ma'] = df['request_count'].rolling(window='7H', min_periods=1).mean()

检测异常:标记超过3倍滚动标准差的数据点

df['rolling_std'] = df['error_count'].rolling('24H').std() df['is_anomaly'] = df['error_count'] > (df['error_count'].rolling('24H').mean() + 3 * df['rolling_std'])

场景三:服务器监控指标

将5分钟精度的CPU负载数据,重采样为每小时最大值

cpu_hourly_max = df['cpu_util'].resample('H').max()

计算过去1小时内的平均负载,每分钟更新一次

df['cpu_1h_rolling_avg'] = df['cpu_util'].rolling(window='1H', min_periods=5).mean()

通过掌握重采样与滑动窗口技术,你可以将原始的时间戳数据,灵活地转换为不同时间粒度下的业务摘要指标,并揭示其随时间变化的趋势与模式,为决策提供强有力的数据支持。

四、文本数据正则提取与结构化

在网络日志、用户行为记录等数据分析中,大量有价值的信息以非结构化的文本形式存在。Pandas 通过其 .str 访问器提供了与正则表达式无缝集成的向量化字符串操作方法,是将这类“脏乱”文本转化为整洁、结构化数据的关键工具。

1. 核心字符串方法与正则表达式

Pandas 的字符串方法是对 Python re 模块的向量化封装,允许对整个 Series 进行高效操作。以下是最核心的几个方法:

2. 正则表达式常用模式与提取实践

a. 基础提取:捕获组的直接应用

最简单的应用是提取单一模式,例如从混杂的字符串中提取数字部分。

提取字符串中的第一个连续数字序列

df['extracted_number'] = df['mixed_column'].str.extract(r'(\d+)')

模式 r'(\d+)' 匹配一个或多个连续数字

b. 多模式与“或”逻辑提取

当目标模式可能有多种变体时,使用“或”运算符 |。

提取特定的标识符,如 “EE”, “EA+”, “EA-”, “AA”

pattern = r'(EE|EA[+-]|AA)' df['identifier'] = df['code_string'].str.extract(pattern)

EA[+-] 使用字符集 [] 同时匹配 “EA+” 和 “EA-”

c. 结构化提取:命名捕获组

对于复杂的文本(如日志行),使用命名捕获组 (?P...) 能极大提升代码可读性和结果的可解释性。

从杂乱的订单日志中提取结构化信息

pattern = r"Order\s+(?P\d+).*?(?P\d{4}-\d{2}-\d{2})" order_info = df['log_text'].str.extract(pattern)

结果 order_info 是一个包含 ‘order_id’ 和 ‘date’ 两列的 DataFrame

3. 实战案例:解析Nginx访问日志

Nginx访问日志是非结构化文本的典型代表。通过正则表达式将其解析为结构化 DataFrame 是后续分析的前提。

a. 定义日志格式与正则模式 假设日志格式为 Nginx combined 格式:

192.168.1.10 - - [28/Aug/2025:14:32:10 +0800] “GET /index.html HTTP/1.1” 200 1024 “-” “Mozilla/5.0”

对应的解析正则表达式和函数如下:

import re
from datetime import datetime

log_pattern = re.compile( r'(?P\S+) - (?P\S+) [(?P.?)] ' r'"(?P\S+) (?P\S+) (?P\S+)" ' r'(?P\d{3}) (?P\d+) "(?P.?)" "(?P.*?)"' )

def parse_nginx_log(line): match = log_pattern.match(line) if match: data = match.groupdict() # 数据类型转换 data['time'] = datetime.strptime(data['time'], '%d/%b/%Y:%H:%M:%S %z') data['status'] = int(data['status']) data['size'] = int(data['size']) return data return None

b. 批量解析并构建DataFrame

records = [] with open('/var/log/nginx/access.log', encoding='utf-8') as f: for line in f: parsed = parse_nginx_log(line) if parsed: records.append(parsed)

df_nginx = pd.DataFrame(records) print(df_nginx.head())

4. 数据清理与结构化的系统流程

将文本日志转化为高质量、可分析的数据集是一个系统工程,遵循以下流程能提高效率:

5. 最佳实践与注意事项

通过上述方法,可以将杂乱的原始文本(如日志、用户输入、产品描述)系统地转化为结构清晰、类型准确、富含特征的结构化数据,为后续的统计分析、聚合与可视化奠定坚实的基础。

五、网络日志(Nginx/Wireshark)解析与统计

承接前文对文本数据正则提取与结构化方法的介绍,网络日志作为典型的非结构化数据源,其解析与统计是运维监控、安全分析和性能优化的核心。本章将深入探讨如何使用 Pandas 高效处理两种最常见的网络日志:Nginx 访问日志与 Wireshark 网络抓包数据,提供从原始文本到深度洞察的完整代码范式。

🔍 Nginx 访问日志解析与多维分析

Nginx 日志通常遵循配置的 log_format,解析的关键在于使用精准的正则表达式将其转换为结构化数据。

1. 日志格式解析与正则表达式

一个包含请求时间的 Nginx main 格式日志示例如下:

192.168.1.10 - - [28/Aug/2025:14:32:10 +0800] “GET /index.html HTTP/1.1” 200 1024 “-” “Mozilla/5.0” “0.003”

对应的正则表达式模式与解析函数如下:

import re
import pandas as pd
from datetime import datetime

定义匹配上述格式的正则表达式(包含命名捕获组)

nginx_log_pattern = re.compile( r'(?P\S+) - (?P\S+) [(?P.?)] ' r'"(?P\S+) (?P\S+) (?P\S+)" ' r'(?P\d{3}) (?P\d+) "(?P.?)" ' r'"(?P.*?)" "(?P[\d.]+)"' )

def parse_nginx_log_line(line): """解析单行Nginx日志""" match = nginx_log_pattern.match(line) if match: data = match.groupdict() # 关键:转换数据类型 data['time'] = datetime.strptime(data['time'], "%d/%b/%Y:%H:%M:%S %z") data['status'] = int(data['status']) data['size'] = int(data['size']) data['req_time'] = float(data['req_time']) # 请求耗时 return data return None # 对于不匹配的行返回None

批量读取日志文件并构建DataFrame

def load_nginx_log_to_df(log_path): records = [] with open(log_path, 'r', encoding='utf-8') as f: for line in f: parsed = parse_nginx_log_line(line) if parsed: # 仅添加成功解析的行 records.append(parsed) df = pd.DataFrame(records)

# 设置时间索引,便于时间序列分析
df.set_index('time', inplace=True)
return df

使用示例

df_nginx = load_nginx_log_to_df('/var/log/nginx/access.log') print(df_nginx.head())

正则表达式详解与技巧:

  • 使用 (?P...) 命名捕获组,使提取的字段在DataFrame中拥有清晰的列名。
  • 时间字段 [(?P.?)] 使用非贪婪匹配 .? 确保只捕获中括号内的内容。
  • 如果日志格式变体或不包含 $request_time,可参考以下更通用的基础模式进行调整: python base_pattern = r'(\d+.\d+.\d+.\d+) - - [([\s\S]+)] "([A-Z]+) ([\S]) ([\S]+)" (\d+) (\d+) "([\S])" "([\S\s]+)"'

2. 核心数据清洗与增强

在解析为DataFrame后,需进行清洗和特征工程以支持深度分析。

1. 处理缺失值与占位符

df_nginx.replace('"-"', pd.NA, inplace=True) # 将“-”表示的缺失转为NaN df_nginx['user'].fillna('anonymous', inplace=True)

2. 标准化文本字段

df_nginx['method'] = df_nginx['method'].str.upper() df_nginx['agent'] = df_nginx['agent'].str.lower().str.slice(0, 100) # 截断过长的User-Agent

3. 类型优化以减少内存

df_nginx['status'] = df_nginx['status'].astype('int16') df_nginx['size'] = df_nginx['size'].astype('int32')

4. 特征工程:提取时间维度

df_nginx['hour_of_day'] = df_nginx.index.hour df_nginx['day_of_week'] = df_nginx.index.day_name() df_nginx['is_weekend'] = df_nginx['day_of_week'].isin(['Saturday', 'Sunday'])

3. 统计分析场景示例

基于结构化的DataFrame,可轻松实现多维度分析。

| 流量概览 | 了解总体访问情况 | df_nginx.shape[0] (总请求数)df_nginx[‘ip’].nunique() (独立访客) | | 状态码分析 | 监控服务健康度 | status_dist = df_nginx[‘status’].value_counts()error_rate = (df_nginx[‘status’] >= 400).mean() | | 性能分析 | 定位慢请求 | df_nginx[‘req_time’].describe() (平均值、分位数)slow_requests = df_nginx[df_nginx[‘req_time’] > 1] | | 资源分析 | 识别热门与缺失资源 | top_urls = df_nginx[‘url’].value_counts().head(10)missing_urls = df_nginx[df_nginx[‘status’] == 404][‘url’].value_counts() | | 安全分析 | 发现潜在攻击 | ip_freq = df_nginx[‘ip’].value_counts()suspicious_ips = ip_freq[ip_freq > 1000].index.tolist() |

具体代码示例:

a. 按小时统计请求量与独立IP数(流量趋势)

hourly_traffic = df_nginx.resample('H').agg({ 'ip': 'count', # 每小时总请求量 'ip': lambda x: x.nunique() # 每小时独立IP数 }).rename(columns={'ip': 'total_requests', 'ip': 'unique_visitors'})

b. 接口(URL)性能TOP10分析

if 'url' in df_nginx.columns and 'req_time' in df_nginx.columns: url_performance = df_nginx.groupby('url').agg( request_count=('req_time', 'count'), avg_response_time=('req_time', 'mean'), p95_response_time=('req_time', lambda x: x.quantile(0.95)) ).round(3) print(url_performance.sort_values('p95_response_time', ascending=False).head(10))

c. 识别异常请求模式(例如,极短时间内的爆发访问)

计算每个IP每分钟的请求数

df_nginx['minute'] = df_nginx.index.floor('T') ip_minute_counts = df_nginx.groupby(['ip', 'minute']).size().reset_index(name='req_per_min')

标记为异常(例如,每分钟请求超过500次)

potential_attack_ips = ip_minute_counts[ip_minute_counts['req_per_min'] > 500]['ip'].unique()

📡 Wireshark 网络抓包日志解析

Wireshark 生成的 .pcap 或 .pcapng 文件包含了更底层的网络流量信息。解析的核心在于将二进制或文本化的抓包数据转化为结构化的 DataFrame。

1. 方法一:使用 PyShark 库直接解析 PCAP 文件

pyshark 库允许在 Python 中直接调用 Wireshark 的解析引擎,无需手动导出。

import pyshark
import pandas as pd

def pcap_to_dataframe(pcap_file, max_packets=5000, display_filter=''): """ 将PCAP文件转换为DataFrame :param pcap_file: 文件路径 :param max_packets: 最大读取包数(用于控制内存) :param display_filter: Wireshark显示过滤器,如 'http' 或 'ip.src==192.168.1.1' :return: 包含数据包信息的DataFrame """ packets = [] cap = pyshark.FileCapture( pcap_file, display_filter=display_filter, only_summaries=False, keep_packets=False # 重要:不保留完整包对象以节省内存 )

try:
    for i, pkt in enumerate(cap):
        if i >= max_packets:
            break
        # 安全地提取字段,避免因协议层缺失而报错
        packet_info = {
            'timestamp': pkt.sniff_time,
            'src_ip': getattr(pkt, 'ip', None) and pkt.ip.src,
            'dst_ip': getattr(pkt, 'ip', None) and pkt.ip.dst,
            'protocol': pkt.highest_layer,
            'length': int(pkt.length),
            'info': pkt.info if hasattr(pkt, 'info') else None
        }
        # 提取端口(如果存在传输层)
        transport_layer = getattr(pkt, 'transport_layer', None)
        if transport_layer:
            layer_obj = getattr(pkt, transport_layer.lower())
            packet_info['src_port'] = getattr(layer_obj, 'srcport', None)
            packet_info['dst_port'] = getattr(layer_obj, 'dstport', None)
        packets.append(packet_info)
except AttributeError as e:
    print(f"跳过解析出错的数据包: {e}")
finally:
    cap.close()

df = pd.DataFrame(packets)
# 数据类型转换
if not df.empty:
    df['timestamp'] = pd.to_datetime(df['timestamp'])
    df['length'] = pd.to_numeric(df['length'], errors='coerce')
print(f"成功解析 {len(df)} 个数据包")
return df

使用示例:只解析HTTP流量

df_packets = pcap_to_dataframe('network_capture.pcapng', max_packets=10000, display_filter='http')

2. 方法二:解析 Wireshark 导出的 CSV 文件

对于快速分析,可先将抓包数据通过 Wireshark 界面导出为 CSV,再用 Pandas 处理。

操作步骤:

  1. 在 Wireshark 中:文件(File) -> 导出分组解析结果(Export Packet Dissections) -> 作为CSV...(As CSV...)。
  2. 选择需要导出的列(如 No., Time, Source, Destination, Protocol, Length, Info)。

读取导出的CSV文件

df_wireshark_csv = pd.read_csv('exported_packets.csv')

数据清洗与转换

重命名列以便理解

df_wireshark_csv.rename(columns={ 'Time': 'timestamp', 'Source': 'src_ip', 'Destination': 'dst_ip', 'Protocol': 'protocol', 'Length': 'length', 'Info': 'info' }, inplace=True)

解析时间戳(格式可能需调整)

df_wireshark_csv['timestamp'] = pd.to_datetime(df_wireshark_csv['timestamp'], errors='coerce')

基础分析示例

print("协议分布:") print(df_wireshark_csv['protocol'].value_counts().head())

流量统计(按源IP)

traffic_by_ip = df_wireshark_csv.groupby('src_ip')['length'].sum().sort_values(ascending=False) print("\n发送流量最大的源IP:") print(traffic_by_ip.head())

3. Wireshark 数据进阶分析

转换为 DataFrame 后,可进行复杂的网络行为分析。

a. 时间序列流量分析

df_packets.set_index('timestamp', inplace=True)

按5分钟重采样,查看流量(包数量)趋势

traffic_trend = df_packets.resample('5T').size() traffic_trend.plot(title='Packet Volume Trend (5-min interval)')

b. 会话/连接分析

定义一个会话键(例如:源IP:端口 -> 目的IP:端口)

def get_session_key(row): return f"{row['src_ip']}:{row.get('src_port')} -> {row['dst_ip']}:{row.get('dst_port')}" df_packets['session'] = df_packets.apply(get_session_key, axis=1)

分析每个会话的数据包数量和总字节数

session_stats = df_packets.groupby('session').agg( packet_count=('length', 'size'), total_bytes=('length', 'sum') ).sort_values('total_bytes', ascending=False)

c. 异常检测:寻找扫描或洪水攻击迹象

计算每个源IP对不同目标端口的连接数(疑似端口扫描)

if 'dst_port' in df_packets.columns: scan_candidates = df_packets.groupby('src_ip')['dst_port'].nunique() potential_scanners = scan_candidates[scan_candidates > 20] # 阈值可调

💡 综合应用与最佳实践