news 2026/10/1 4:54:32

基于CNN的网络入侵检测实战:从特征编码到模型部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于CNN的网络入侵检测实战:从特征编码到模型部署

简介:基于卷积神经网络实现网络入侵检测的完整项目代码包,面向希望掌握深度学习与网络安全结合应用的小白和进阶学习者,适合用于毕业设计、课程设计或工程实训。包内提供数据预处理脚本、一层全连接层对照代码和CNN主程序,配套KDD Cup数据集压缩包及TensorBoard训练日志,可复现99.5%的检测正确率。资源共16个文件,以Python脚本、gzip压缩数据集、项目配置XML和说明文档为主,整体大小约17.52MB,目录结构清晰。目前已有105人学习下载。通过阅读源码和训练日志,读者能理解CNN处理网络流量的思路,对比全连接层与卷积神经网络的性能差异,并根据准确率与损失曲线进行参数调整,是快速上手入侵检测项目的实用资料;包内还附工程配置与使用说明,便于直接导入项目并按需调整。

1. 网络入侵检测搭上卷积神经网络:为什么流量识别也要“看图”

网络入侵检测最麻烦的不是抓不到流量,而是不知道“正常”长什么样。规则引擎靠专家逐条写特征,遇到慢速扫描、低频爆破这类不刷屏的攻击经常漏;传统机器学习方案又极度依赖特征工程的质量。基于卷积神经网络的网络入侵检测走的是另一条路:不逐条定义攻击模式,而是把网络连接的特征向量重排成类似图像的二维矩阵,让卷积神经网络(CNN)自动抽取局部规律。在NSL-KDD这类公开基准集上,二分类正确率达到99.5%并不算夸张,真正的问题在于怎么复现它、怎么看这个数字、以及上线时怎么让它不翻车。这篇笔记围绕数据编码、模型搭建、参数设置和部署踩坑展开,适合流量分析、安全网关和IDS产品验证方向的人照着自己跑一遍。

2. 流量数据先变成张量:NSL-KDD选型、特征编码与二维重构

CNN吃进去的是矩阵,不是pcap文件,所以在谈模型之前,得先把“网络连接”这种结构化记录变成能放进卷积层的数字张量。做入侵检测的团队经常忽略这一步,结果模型结构再漂亮也救不回错误的数据表示。

2.1 数据集怎么选:NSL-KDD、UNSW-NB15和CICIDS 2017

数据集决定了你的实验能跑多快、结论能信多少。我一般先看NSL-KDD:训练集约12.5万条、测试集约2.2万条,每条样本41维特征,标签分Normal和4类攻击(DoS、Probe、R2L、U2R)。它去掉了KDD Cup 99里大量冗余重复记录,类别分布相对合理,整轮训练在普通GPU上几分钟完成,适合先验证网络结构和参数。

UNSW-NB15是比NSL-KDD更新一点的选项,49维特征、9类攻击,攻击面更贴近现代网络,但样本量达到百万级,预处理和训练都更慢。CICIDS 2017则是从原始PCAP重放出来的数据集,特征超过80维,最接近真实会话流,但需要自己决定怎么从抓包中抽特征,工程量明显更大。做第一版模型验证,NSL-KDD性价比最高。

数据集样本规模特征数攻击类别适合阶段
NSL-KDD训练约12.5万,测试约2.2万414类加正常模型选型、参数迭代
UNSW-NB15百万级499类加正常跨数据集泛化验证
CICIDS 2017百万级80以上14类加正常真实场景模拟、端到端验证

选好数据集后,下一个问题是:这些数据集里的特征列,CNN不能直接读。卷积神经网络原理上是在二维网格里找局部模式,把协议类型、连接时长、窗口统计这些字段按某种顺序排成矩阵,卷积核才能学到“相邻位置特征之间的组合关系”,这正是CNN相比全连接网络的一个优势——特征的空间排布天然带有抽象语义。

2.2 41维特征怎么编码成11x11矩阵

NSL-KDD的41维特征里,有3个是离散的:protocol_type(协议类型)、service(目标服务)、flag(连接状态)。剩下38个是连续数值,比如duration、src_bytes、dst_bytes,以及大量基于时间窗口的统计特征,像是count、serror_rate、dst_host_srv_count。离散字段不能直接当数值用——把tcp编码成1、udp编码成2,模型会莫名其妙学到“udp大于tcp”这种不存在的序关系。

常见做法是独热编码展开。protocol_type有3种取值、service约70种、flag约11种,三个离散字段展开后新增81个维度,加上38个连续特征,总维度变成122。图像格式一般选单通道灰度图,所以需要把122维向量重排成二维矩阵。12x10等于120维度还缺2个,11x11等于121维度缺1个,补零是最省事的方案;也有做法直接截断到120维,但我倾向补零,保留完整信息量,卷积核自己会学到边缘补零位置不重要。

2.3 reshape策略:特征排列顺序影响感受野

特征重排成矩阵后,排列顺序不能随便来。卷积神经网络结构图里最直观的一点是:3x3卷积核每次只看见相邻的9个格子。如果相邻位置放的是语义上完全无关的特征,卷积核学到的“局部模式”就没有物理含义,模型准确率会有波动,而且这种波动在调参阶段让你分不清是结构问题还是排列问题。

经验做法是把同一来源或同一时段的统计特征放在相邻位置。比如count、srv_count、serror_rate、srv_serror_rate这四个都描述“最近一段时间内连接行为”,把它们排在一起,卷积核更容易捕捉到“同一时段的连接数异常且错误率高”这种攻击模式。离散特征展开后的独热位放到矩阵边缘,连续数值特征集中在中间区域。下面这个预处理脚本可以直接套到NSL-KDD上:

import pandas as pd import numpy as np from sklearn.preprocessing import StandardScaler # NSL-KDD 的41列特征名,按原始顺序 FEATURES = [ 'duration', 'protocol_type', 'service', 'flag', 'src_bytes', 'dst_bytes', 'land', 'wrong_fragment', 'urgent', 'hot', 'num_failed_logins', 'logged_in', 'num_compromised', 'root_shell', 'su_attempted', 'num_root', 'num_file_creations', 'num_shells', 'num_access_files', 'num_outbound_cmds', 'is_host_login', 'is_guest_login', 'count', 'srv_count', 'serror_rate', 'srv_serror_rate', 'rerror_rate', 'srv_rerror_rate', 'same_srv_rate', 'diff_srv_rate', 'srv_diff_host_rate', 'dst_host_count', 'dst_host_srv_count', 'dst_host_same_srv_rate', 'dst_host_diff_srv_rate', 'dst_host_same_src_port_rate', 'dst_host_srv_diff_host_rate', 'dst_host_serror_rate', 'dst_host_srv_serror_rate', 'dst_host_rerror_rate', 'dst_host_srv_rerror_rate' ] def load_and_encode(train_df, test_df): # 合并train/test做独热展开,保证两边列集合完全一致 all_x = pd.concat([train_df.drop('label', axis=1), test_df.drop('label', axis=1)], axis=0) encoded = pd.get_dummies(all_x, columns=['protocol_type', 'service', 'flag']) train_enc = encoded.iloc[:len(train_df)].reset_index(drop=True) test_enc = encoded.iloc[len(train_df):].reset_index(drop=True) # 重点:scaler只fit训练集,测试集只做transform,避免信息泄漏 scaler = StandardScaler().fit(train_enc) X_train = scaler.transform(train_enc).astype('float32') X_test = scaler.transform(test_enc).astype('float32') # 122维补1个零到121维,再reshape成11x11x1 def to_image(X): n = X.shape[0] X_pad = np.pad(X, ((0, 0), (0, 1)), mode='constant') return X_pad.reshape(n, 11, 11, 1) return to_image(X_train), to_image(X_test)

逻辑说明:先合并train/test做独热展开,是为了避免service字段在训练集和测试集中取值集合不一致,导致两边的列数对不上;StandardScaler用fit_transform和transform分开调用,是防止测试集的均值方差信息提前混进特征;最后np.pad在第122个位置补0,凑成121维,再reshape成11x11的单通道灰度图。

参数说明:缩放方式选了StandardScaler而不是MinMaxScaler,是因为网络流量统计特征有长尾分布,标准化后梯度更稳定。如果你用的是UNSW-NB15这类49维数据集,需要重新算独热展开后的维度,再调整reshape尺寸,比如补零到9x9或12x12都可行,原则是让语义相关的特征落在相邻格子里。

3. CNN入侵检测模型怎么搭:卷积核、池化与三个关键参数

数据变成张量后,模型部分反而简单。入侵检测是数据量相对小的分类任务,不需要套ResNet那种上百层的深度网络,两到三个卷积块加一个全连接层就能跑出很高的基准。真正拉开差距的是卷积核数量的设置、Dropout的位置、以及训练时的早停策略。

3.1 基础结构:两层卷积块加全连接,为什么不用深网络

我常用的CNN入侵检测结构长这样:输入一个11x11x1的灰度图,第一个卷积块包含32个3x3卷积核,卷积后接BatchNorm和ReLU,再做一次2x2最大池化;第二个卷积块换成64个3x3卷积核,同样接BatchNorm、ReLU和池化;然后Flatten压平,接一个128节点的全连接层,Dropout比例0.5,最后输出层按二分类或五分类接softmax。

第一层32个卷积核学习的是基础流量模式,比如连接数窗口统计、协议类型组合、错误率局部异常;第二层64个卷积核在更高层把前面学到的模式组合起来,对应“某个目标主机在时间窗口内出现大量不同源端口连接”这类攻击语义。MaxPooling把11x11降到5x5再降到2x2,既降了计算量,又保留了激活最强的特征。为什么不用更深的网络?NSL-KDD只有十几万训练样本,深层模型参数量上去了过拟合很快,而且加深一两层带来的准确率提升通常不到0.5%,不值得引入额外的调参和训练成本。

import tensorflow as tf from tensorflow.keras import layers, models def build_cnn(num_classes=2): model = models.Sequential([ layers.Input(shape=(11, 11, 1)), # 卷积块1:学基础流量局部模式 layers.Conv2D(32, 3, padding='same', activation='relu'), layers.BatchNormalization(), layers.MaxPooling2D(pool_size=2), # 卷积块2:在基础模式之上组合攻击语义 layers.Conv2D(64, 3, padding='same', activation='relu'), layers.BatchNormalization(), layers.MaxPooling2D(pool_size=2), layers.Flatten(), layers.Dense(128, activation='relu'), layers.Dropout(0.5), layers.Dense(num_classes, activation='softmax') ]) return model

逻辑说明:Conv2D用3x3卷积核、padding='same',保证特征图边缘信息不提前丢失;BatchNorm放在卷积层后面、激活函数前面,对网络流量这种分布变化大的输入,能显著稳定训练过程;Dropout放在全连接层前,是CNN里对抗过拟合最有效的常规位置,卷积层本身有参数共享和池化做正则,不需要额外加Dropout。

参数说明:第一层卷积核32个、第二层64个是稳妥起步。如果验证集准确率上不去,可以试着提到64/128,但参数量会翻倍,在小数据集上收益有限。激活函数统一用ReLU,二分类输出层用softmax而不是sigmoid,这样后面分析概率阈值时更方便。

3.2 三个必调参数:卷积核数量、Dropout比例、学习率

CNN入侵检测模型跑起来后,真正影响落地效果的参数就三个。第一个是卷积核数量,32/64起步,模型欠拟合时加一倍,但不要反复加——加到128以上在NSL-KDD上几乎看不到提升,只增加了训练时间。第二个是Dropout比例,全连接层前我固定0.5;如果你发现验证集损失和训练集损失差得很大,把Dropout提到0.6试试。第三个是学习率,Adam优化器默认0.001基本不用改;收敛太慢时降到0.0003比直接改动网络结构更有效。这三个参数调到合理范围后,别急着继续调,先看数据有没有泄漏、类别是不是不平衡,那才是让准确率虚高的主因。

3.3 早停与学习率衰减:让训练自己停下来

early_stop = tf.keras.callbacks.EarlyStopping( monitor='val_loss', patience=10, restore_best_weights=True ) reduce_lr = tf.keras.callbacks.ReduceLROnPlateau( monitor='val_loss', factor=0.5, patience=5, min_lr=1e-6 )

逻辑说明:EarlyStopping监控验证集损失,连续10轮不下降就停止训练,restore_best_weights会回滚到验证集损失最低时的权重,这个回滚很重要,否则保存下来的可能是过拟合后的模型。ReduceLROnPlateau在验证损失连续5轮不下降时把学习率减半,用来跨过局部平稳区域,min_lr=1e-6防止学习率衰减到完全学不动。

参数说明:epoch设置50就够,配合上面两个回调,实际训练通常20到30轮就停了。patience设太小容易在准确率还没爬上去时就早停,设太大浪费时间,10和5是我在NSL-KDD上比较稳的组合。

4. 复现99.5%的完整训练流程:数据加载、训练配置与指标评估

结构定了,参数定了,接下来就是端到端训练。这一章要解决一个核心问题:在什么时候、用什么配置,才能稳定复现出99.5%这个数字,以及这个数字到底该怎么读。

4.1 训练配置:固定随机种子和分层切分

复现实验结果最怕的是每次跑出来的准确率忽高忽低。差异主要来自两个地方:模型初始化时卷积核的随机权重、以及训练/验证切分时的样本分布。解决办法是固定随机种子,并且按类别比例分层切分。

import numpy as np import tensorflow as tf from sklearn.model_selection import train_test_split from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau np.random.seed(42) tf.random.set_seed(42) # 二分类标签:normal为0,所有攻击合并为1 y_train_bin = (train_df['label'] != 'normal').astype('int') y_test_bin = (test_df['label'] != 'normal').astype('int') # 如果不用官方测试集,按分层留10%做验证集 X_tr, X_val, y_tr, y_val = train_test_split( X_train_data, y_train_bin, test_size=0.1, stratify=y_train_bin, random_state=42 ) model = build_cnn(num_classes=2) model.compile( optimizer=tf.keras.optimizers.Adam(0.001), loss='sparse_categorical_crossentropy', metrics=['accuracy'] ) history = model.fit( X_tr, y_tr, validation_data=(X_val, y_val), batch_size=64, epochs=50, callbacks=[ EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True), ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5, min_lr=1e-6) ], verbose=1 ) test_loss, test_acc = model.evaluate(X_test_data, y_test_bin, verbose=0) print(f'test acc: {test_acc:.4f}')

逻辑说明:random_state=42和tf.random.set_seed(42)要在数据切分和模型构建之前完成,否则模型初始化顺序不同,结果仍会有细微差异。stratify=y_train_bin保证切出来的验证集里normal和attack比例和原始训练集一致,避免验证集里全是normal导致评估失真。

参数说明:batch_size=64在12万条样本上迭代速度合适,想更稳可以降到32;损失函数用sparse_categorical_crossentropy,配合整数标签,不需要手动做one-hot。评估时直接拿官方测试集跑,这样和别人论文里的结果有可比性。

4.2 正确率99.5%是怎么来的:混淆矩阵和分类报告比一个数字诚实

正确率本身是个很有迷惑性的指标。如果测试集里正常流量占大多数,把样本全部判成正常,正确率也会有九成以上。所以在宣称“正确率99.5%”之前,一定要把混淆矩阵和分类报告打出来看一眼。

from sklearn.metrics import confusion_matrix, classification_report y_pred = np.argmax(model.predict(X_test_data), axis=1) print(confusion_matrix(y_test_bin, y_pred)) # 输出格式:[[TN, FP], [FN, TP]] print(classification_report(y_test_bin, y_pred, target_names=['normal', 'attack'], digits=4))

逻辑说明:混淆矩阵的四个格子能直接看出模型是偏向把正常流量误判成攻击(FP高),还是把攻击漏成正常(FN高)。分类报告里的precision和recall分别反映“报出来的攻击里有多少是真的”和“真正的攻击里有多少被抓住”,这两个数是上线前最该盯住的指标。

参数说明:digits=4让指标保留四位小数,方便对比实验间的细微差异。在NSL-KDD二分类任务里,模型通常能到0.99以上的precision和recall,这也是99.5%这个数字的主要来源。

4.3 二分类和五分类的路径差异:attention与class_weight

二分类是“攻击还是正常”,五分类则需要区分DoS、Probe、R2L、U2R这些攻击类型。五分类难度高不少,因为R2L和U2R在NSL-KDD里的样本量非常少,U2R整个训练集才几十条,模型很容易把它们学成噪声。遇到这种情况,class_weight比改网络结构更直接:

from sklearn.utils.class_weight import compute_class_weight classes = np.unique(y_train) weights = compute_class_weight('balanced', classes=classes, y=y_train) class_weight = dict(zip(classes, weights)) model.fit( X_tr, y_tr, validation_data=(X_val, y_val), class_weight=class_weight, batch_size=64, epochs=50, callbacks=[...], verbose=1 )

逻辑说明:compute_class_weight会按样本量反比给每个类别分配权重,稀有类权重高,在损失函数里相当于多给几条样本,让模型不直接把它们忽略掉。加了class_weight后,R2L和U2R的recall能改善不少,但整体正确率通常会微降,这是正常现象——你是在拿一点点整体准确率换稀有类的检出率。

5. 高正确率背后的避坑清单:数据泄漏、类别不平衡与指标幻觉

99.5%的正确率看起来漂亮,实际踩坑时会发现,这个数字有一大半是数据分布给的,不是模型多聪明。这一章写清我在复现过程中遇到的5个典型问题,每个都按现象、原因、解决来拆。

5.1 归一化泄漏:为什么你复现出来的结果比论文还好

现象:训练集准确率99.9%,测试集准确率99.5%,怎么看都漂亮,但你隐约觉得哪里不对——换了一组真实流量数据后,准确率直接掉到85%。

原因:做特征缩放时,用StandardScaler对train和test合并后的全部数据做了fit_transform。测试集的均值和方差提前混进了特征缩放统计量,模型在测试时已经“见过”了测试集的分布信息,这不是真实的泛化能力。

解决:严格按本文2.2的写法,scaler只fit在训练集上,测试集单独调用transform。更严格一点,连独热编码的列集合都只从训练集导出。可以用一个简单方式自查:在训练脚本里打印scaler.mean_的长度和训练集特征数,如果对不上,说明编码阶段的数据范围就不对。

5.2 类别不平衡:U2R和R2L的recall为什么可能是0

现象:整体正确率95%,但打开分类报告,U2R那一行的recall是0.00,R2L只有0.12。所有U2R样本全部被预测成normal或DoS。

原因:NSL-KDD里U2R样本太少,模型在训练时几乎没见过这个类别,梯度更新被majority class主导。正确率是高了,但模型实际上是个偏科生。

解决:先看分类报告,不要只看acc。然后按4.3加class_weight,或者对稀有类做SMOTE过采样。如果业务必须检出U2R,还可以把问题重新组织成“正常vs四类攻击”的单分类器,把稀有类检出的优先级提到准确率之前。

5.3 切分数据时泄漏了同源会话

现象:随机切分一个训练/测试集后,准确率极高;换成按时间切分,同一个模型掉3到5个点。

原因:NSL-KDD里存在来自同一个网络会话的多个流量记录,随机切分会把同源记录同时分到训练集和测试集,相当于测试集里出现了训练样本的近亲副本。

解决:尽量使用官方预设的KDDTrain+和KDDTest+划分,不要自己随机切分。如果要自己切,先按源IP或会话ID分组,再对组做切分,避免同源记录跨集合。

5.4 固定了seed但换机器结果还是变

现象:同一份代码在同一台机器上跑,结果稳定。换一台机器或换一个TensorFlow版本,准确率掉了1到2个百分点。

原因:GPU算子浮点累加顺序、TF底层算子调度、cuDNN算法选择都会引入非确定性。seed只能控制Python层级的随机数,控制不了底层并行计算的微小差异。

解决:记录训练环境的TensorFlow版本、CUDA版本和GPU型号。如果项目对复现要求高,用CPU训练或开启TF的确定性算子开关,代价是训练慢一些。反正NSL-KDD数据集小,CPU跑也就几分钟,完全能接受。

5.5 指标幻觉:准确率99.5%上线后误报刷屏

现象:基准集上一切正常,接入真实网关后,正常业务流量被频繁判为攻击,安全运营一天收到上千条告警。

原因:真实网络流量的特征分布和NSL-KDD差别很大。基准集里的攻击流量是结构化样本,真实流量里大量P2P传输、视频流、长连接握手和内部扫描工具的特征,在模型眼里都和“异常”很像。正确率在两个分布下含义完全不同。

解决:上线前用真实业务流量回放,计算误报率而不是正确率。误报率的定义是“正常流量被判为攻击的比例”,按这个指标调阈值或加规则。另外,线上模型最好从二分类降级到多分类,只对明确攻击类型告警,模糊预测不告警。

6. 从实验台挪到网关:部署CNN入侵检测器的延迟与误报处理

模型在基准集上跑通只是第一步。把CNN入侵检测器接入真实链路时,要处理模型导出、在线推理延迟、误报压制三个问题。这一章讲我最常用的部署做法。

6.1 模型导出与推理管线的最小形态

# 保存Keras模型,供后续加载推理 model.save('cnn_nids_model.keras')

在线推理管线一般长这样:实时抓包后按会话聚合连接记录,提取NSL-KDD同款41维特征,加载训练时保存的scaler做transform,补零后reshape成11x11x1,送入模型拿到softmax概率。单条样本推理在CPU上是毫秒级,瓶颈通常在会话聚合的等待时间。如果每秒要处理上千条连接,把推理改成batch模式跑,吞吐会高很多。

6.2 误报压制:滑动窗口多数投票和阈值调整

单条流量判异常并不等于告警。我上线时加了两层保护:第一层,取最近5个会话的预测概率做滑动窗口平均,超过告警阈值才触发;第二层,对新告警做同源IP聚合,短时间内同一源IP的多次告警合并成一条事件,避免告警风暴。阈值一般不用默认的0.5,可以按验证集P/R曲线选一个偏保守的值,比如0.7,让告警更精确。

6.3 上线前的一个验证习惯

我现在的习惯是:无论在基准集上跑出多高的正确率,正式上线前都会拿真实流量pcap回放一遍,统计误报率和单条延迟。98%以上的准确率只是入场券,能把误报率摁在业务能接受的范围内,才算真的落地。如果你正准备把这个方向带到生产环境,建议从NSL-KDD小步验证,再逐步换成UNSW-NB15和真实流量,一路把阈值、窗口和告警策略都磨一遍。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 4:54:31

并行归约、区间贪心与树状数组:execution环境下的算法工程实践

最近在做一套综合性的算法与计算优化练习,项目标题是“execution并行归约|区间贪心|树状数组”。乍一看这三个词像是从不同教科书里硬凑出来的——并行归约是高性能计算里的经典操作,区间贪心是算法设计课的常客,树状数组则是竞赛选手人手一份的数据结构。但把它们放到同一个执…

作者头像 李华
网站建设 2026/10/1 4:53:34

Jev架构:面向业务执行闭环的AI决策系统范式

1. Jev 不是新名词,而是决策系统演进的必然结果你可能在最近几周的技术社区、架构分享会甚至招聘JD里反复看到“Jev”这个词——它不像Transformer或Diffusion那样自带论文出处,也不像Kubernetes或Flink那样有明确的开源仓库和版本号。它没有官网首页弹窗…

作者头像 李华
网站建设 2026/10/1 4:52:48

Keil调试实战指南:从环境配置到HardFault排查,把调试窗口用起来

Keil软件程序调试学习笔记:从环境配置到实战排查,把调试窗口真正用起来做嵌入式开发的人,几乎没人绕得过Keil。不管你是刚点完LED灯的新手,还是正在调电机FOC的老手,只要你手上跳过的板子用的是STM32、GD32、C51&#…

作者头像 李华
网站建设 2026/10/1 4:52:47

Codex接入Jev完整指南:配置、踩坑与本地部署实践

Codex 这个终端里的 AI 编程助手,最近在开发者圈子里热度一直没下来。它的定位和传统的补全插件完全不同——不是帮你少敲几行代码,而是像一个坐在终端里的初级工程师:给它一个任务,它自己读仓库、定位问题、改文件、跑命令&#…

作者头像 李华
网站建设 2026/10/1 4:52:14

磁盘空间分析器怎么选?8款工具实测对比,揪出空间大户

磁盘空间分析器这活儿,说大不大,说小也不小。我见过太多人宁可每天被系统盘爆红的弹窗烦着,也不愿意花十分钟装个趁手的分析工具;也见过有人装了一堆所谓“清理大师”,结果该占的磁盘一处没少,还搭进去一堆…

作者头像 李华
网站建设 2026/10/1 4:52:08

AI日报系统设计与实现:从RSS抓取到本地LLM摘要

我无法基于当前输入生成符合要求的博文。原因如下:输入中仅提供了项目标题【AI 日报 2026年9月21日 星期一】,以及空置的“相关热搜词”“最新网络热词”和完全空白的“基于标题及热词网络搜索的内容”字段;根据你的核心任务定义&#xff0c…

作者头像 李华