变压器DGA油色谱数据建模避坑指南:从数据体检到随机森林基线
简介这份变压器溶解气体数据.rar面向电力设备运维、故障诊断研究与机器学习建模人员聚焦变压器油中溶解气体分析这一典型场景帮助解决故障类型识别与状态评估问题。数据覆盖中低温过热、高温过热、低能放电、高能放电、局部放电及正常状态六类样本涉及氢气、甲烷、乙烷、乙烯、乙炔等特征气体的浓度规律可用于比值法、判别函数法及智能诊断算法的验证与对比。压缩包约6.97MB文件总数与类型明细上游暂未提供但整体体量轻便便于快速下载与本地实验。目前已有177人学习下载具备一定参考热度。读者可借助实测数据开展特征工程、分类模型训练与故障预测实验理解不同故障下气体生成规律为智能监控系统开发和电力系统可靠性研究提供数据支撑。1. 变压器溶解气体数据.rar一份油色谱数据到手后先别急着训练模型拿到一个名为「变压器溶解气体数据.rar」的压缩包很多人的第一反应是解压、读表、扔进模型跑一遍准确率。但真正做过电力设备状态评估的人会先停一下这份数据到底是 DGADissolved Gas Analysis油中溶解气体分析的原始浓度记录还是已经被人为标注过故障类型的分类数据集两种情况下后面的处理路径完全不同。变压器溶解气体数据在工程里通常对应七种特征气体——氢气、甲烷、乙烷、乙烯、乙炔、一氧化碳、二氧化碳有时还带总烃和微水。这些数值背后是油纸绝缘在过热、放电、受潮等不同劣化机制下产气规律的变化。这份数据能解决的问题很具体用气体浓度组合去判断设备是否存在潜伏性故障以及故障大概属于哪一类。适合谁做电力设备在线监测、状态检修、故障诊断的算法工程师以及想把 DGA 数据用起来的运维分析人员。如果你只是想要一个干净的特征表直接调库那大概率会在数据清洗和标签定义上翻车。2. 先搞清楚七种气体和三类标签DGA 数据的字段含义与选型逻辑2.1 七种特征气体的物理意义与量纲陷阱油中溶解气体不是随便选的七个指标。氢气主要来自局部放电和水分分解甲烷、乙烷是低温过热产物乙烯在较高温度过热时显著上升乙炔则是高能放电的典型标志浓度一高基本可以锁定电弧或火花放电。一氧化碳和二氧化碳反映固体绝缘纸的劣化。问题在于很多压缩包里的数据表只给列名不给单位。常见单位有 μL/L即 ppm和 mg/L 两种前者是体积分数后者是质量浓度数值能差出好几倍。我一般会先看乙炔那一列的数值范围如果最大值只有零点几大概率是 ppm如果出现几十甚至上百要么是严重故障样本要么单位是别的。另一个坑是「总烃」列它通常是甲烷到乙炔四者之和如果数据里既有分项又有总烃训练时不要同时放进去否则共线性会让树模型的重要性排序失真。2.2 标签体系三比值、大卫三角和故障类型编码DGA 数据最常见的标签来源是 IEC 三比值法或罗杰斯比值法也有用大卫三角的。三比值用 C2H2/C2H4、CH4/H2、C2H4/C2H6 三个比值编码每个比值分区间给 0、1、2 三档组合成故障类型。如果你拿到的数据里有一列「故障类型」写着「低温过热」「中温过热」「高温过热」「局部放电」「火花放电」「电弧放电」这类中文那基本就是按比值法或改良版标注的。选型时要注意如果标签是规则生成的模型学到的其实是规则本身换一批数据可能就不准如果标签来自实际检修结论样本量通常很小且类别极不平衡。我的做法是先把标签分布打出来少于 30 个样本的类别要么合并要么用分层抽样别硬做多分类。2.3 用 pandas 读压缩包并做第一轮体检拿到 .rar 文件Windows 上可以用 7-Zip 或 WinRAR 解压Linux 下用 unrar。解压后常见格式是 .xlsx 或 .csv。下面这段代码做三件事读表、看字段、查缺失和量纲异常。import pandas as pd import numpy as np # 读入解压后的 csv注意编码可能是 gbk 或 utf-8 df pd.read_csv(dga_data.csv, encodinggbk) # 统一列名去掉空格和括号 df.columns [c.strip().replace(, ().replace(, )) for c in df.columns] # 查看前五行和字段类型 print(df.head()) print(df.dtypes) # 七种气体列名按实际表头调整 gas_cols [H2, CH4, C2H6, C2H4, C2H2, CO, CO2] # 缺失值统计 print(df[gas_cols].isnull().sum()) # 描述性统计重点看 min 和 max 判断量纲 print(df[gas_cols].describe().loc[[min, max, mean]]) # 检查是否有负值气体浓度不应为负 for col in gas_cols: neg_count (df[col] 0).sum() if neg_count 0: print(f{col} 存在 {neg_count} 个负值需要处理)逻辑说明先统一列名是为了后续按固定列名索引避免因为空格或全半角括号导致 KeyError。缺失值统计能告诉你哪些气体列是「稀疏」的比如乙炔在很多正常样本里就是 0 或未检出这不是缺失而是真实工况。描述性统计里的 max 值如果远大于 mean说明有极端故障样本后面标准化时要考虑用 RobustScaler 而不是 StandardScaler。负值直接置为 0 或按缺失处理因为浓度不可能为负。参数说明encoding参数要根据实际文件调整中文表头常见 gbk如果报 UnicodeDecodeError 就换 utf-8 或 gb18030。gas_cols列表必须和表头完全一致大小写敏感。如果表头是中文「氢气」「甲烷」要么改列表要么在读入后重命名。3. 从原始浓度到可训练特征比值、编码和标准化怎么做3.1 三比值编码的代码实现与边界处理三比值法的核心是把三个比值映射到整数编码。下面这段代码按 IEC 60599 的常见分区实现注意分母为 0 的情况。def ratio_code(df): # 避免分母为 0加一个极小值 eps 1e-6 df df.copy() # C2H2/C2H4 r1 df[C2H2] / (df[C2H4] eps) # CH4/H2 r2 df[CH4] / (df[H2] eps) # C2H4/C2H6 r3 df[C2H4] / (df[C2H6] eps) def code_r1(x): if x 0.1: return 0 elif x 3: return 1 else: return 2 def code_r2(x): if x 0.1: return 1 elif x 1: return 0 else: return 2 def code_r3(x): if x 1: return 0 elif x 3: return 1 else: return 2 df[code1] r1.apply(code_r1) df[code2] r2.apply(code_r2) df[code3] r3.apply(code_r3) df[ratio_combo] df[code1].astype(str) df[code2].astype(str) df[code3].astype(str) return df df ratio_code(df) print(df[ratio_combo].value_counts())逻辑说明加 eps 是为了防止分母为 0 导致除零错误但要注意如果 H2 本身是 0CH4/H2 会变成一个极大值编码会落到最高档。实际工程中H2 为 0 且 CH4 也接近 0 的样本通常是正常老化直接归到正常类更合理。ratio_combo把三个编码拼成字符串方便做分组统计或独热编码。如果要做多分类可以把 combo 映射到故障类型但映射表要按你采用的导则来不同导则的分区边界有差异。参数说明eps取 1e-6 是经验值太小可能受浮点精度影响太大可能改变比值量级。三个 code 函数的边界值 0.1、1、3 来自常见三比值分区如果你的数据标签是按其他导则生成的边界要相应调整。3.2 标准化与不平衡处理为什么不能直接上 SMOTE七种气体的浓度跨度极大乙炔可能是个位数二氧化碳可能上千。不做标准化基于距离的模型KNN、SVM会被大数值列主导。我一般用 RobustScaler因为它对异常值不敏感。下面代码同时做标准化和类别权重计算。from sklearn.preprocessing import RobustScaler from sklearn.utils.class_weight import compute_class_weight gas_cols [H2, CH4, C2H6, C2H4, C2H2, CO, CO2] X df[gas_cols].values y df[fault_type].values # 假设标签列叫 fault_type scaler RobustScaler() X_scaled scaler.fit_transform(X) # 计算类别权重用于模型训练 classes np.unique(y) weights compute_class_weight(balanced, classesclasses, yy) class_weight_dict dict(zip(classes, weights)) print(class_weight_dict)逻辑说明RobustScaler 用中位数和四分位距做缩放比 StandardScaler 更适合含极端故障样本的 DGA 数据。compute_class_weight给出每个类别的权重训练时传给模型的class_weight参数比直接过采样更稳妥。为什么不推荐 SMOTE因为 DGA 样本的特征空间不是欧氏的两个故障样本之间做线性插值可能生成物理上不存在的浓度组合比如乙炔和乙烯的比例关系被破坏模型学到的是假模式。参数说明class_weightbalanced会按类别频率反比给权重频率低的类别权重大。如果某个类别只有几个样本权重会非常大可能导致模型偏向该类别这时可以考虑合并稀有类或改用 focal loss。3.3 特征工程除了比值还能加什么原始七种气体加三个比值编码是最小特征集。实际项目中我还会加几个衍生特征总烃CH4C2H6C2H4C2H2、乙烯占比C2H4/总烃、乙炔占比C2H2/总烃、CO2/CO 比值。CO2/CO 比值对区分固体绝缘劣化和油劣化有帮助一般大于 7 认为纸绝缘正常小于 3 要警惕。这些特征不需要复杂计算但能显著提升树模型的分裂效果。注意不要加太多高度相关的特征否则特征重要性会分散解释性变差。4. 避坑与排查DGA 数据建模中最容易翻车的五个地方4.1 现象模型准确率 99%换一批数据掉到 60%原因标签是规则生成的且训练集和测试集来自同一批规则标注的数据模型学的是规则边界而不是真实故障模式。解决如果标签来自三比值法直接查表输出结果即可不需要训练模型如果一定要用机器学习确保测试集来自不同时间段或不同设备并且标签来自检修结论而非规则。4.2 现象乙炔列大量为 0模型完全忽略这个特征原因乙炔在正常样本中普遍未检出数值为 0但在故障样本中可能很高。如果直接标准化0 值会被缩放到负值区间树模型虽然不受影响但线性模型会出问题。解决对乙炔单独做二值化特征「乙炔是否检出」再保留原始浓度。或者用对数变换 log1p 压缩量纲。4.3 现象训练时 loss 震荡验证集准确率不上升原因学习率太大或者批次里混入了极端值样本。DGA 数据中个别故障样本的乙炔浓度可能是正常值的几百倍梯度会被拉爆。解决先用 RobustScaler 缩放再检查是否有超过 10 倍四分位距的离群点必要时截断或单独分析。学习率从 1e-3 降到 1e-4 试试。4.4 现象三比值编码后某些组合从未出现原因样本量太小或者数据采集时已经过滤掉了某些故障类型。三比值有 27 种组合实际数据可能只覆盖 8 到 10 种。解决不要强行做 27 类分类把稀有组合合并到「其他故障」或按故障大类过热、放电、受潮重新标注。4.5 现象用 CO2 和 CO 做特征后模型性能下降原因CO2 和 CO 受油中气体扩散和吸附剂影响大且与故障类型的关系不如烃类气体直接。解决可以保留但降低权重或者只保留 CO2/CO 比值。如果数据里 CO2 列缺失严重直接去掉。5. 一个可复现的基线用随机森林做 DGA 故障分类并验证5.1 完整训练脚本与交叉验证下面这段代码从读数据到输出分类报告是一条能跑通的最小路径。假设数据已经解压为 csv标签列名为 fault_type。import pandas as pd import numpy as np from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import StratifiedKFold, cross_val_predict from sklearn.preprocessing import RobustScaler from sklearn.metrics import classification_report, confusion_matrix # 读数据 df pd.read_csv(dga_data.csv, encodinggbk) df.columns [c.strip() for c in df.columns] gas_cols [H2, CH4, C2H6, C2H4, C2H2, CO, CO2] df df.dropna(subsetgas_cols [fault_type]) # 衍生特征 df[total_hydrocarbon] df[CH4] df[C2H6] df[C2H4] df[C2H2] df[C2H4_ratio] df[C2H4] / (df[total_hydrocarbon] 1e-6) df[C2H2_ratio] df[C2H2] / (df[total_hydrocarbon] 1e-6) df[CO2_CO_ratio] df[CO2] / (df[CO] 1e-6) feature_cols gas_cols [total_hydrocarbon, C2H4_ratio, C2H2_ratio, CO2_CO_ratio] X df[feature_cols].values y df[fault_type].values # 标准化 scaler RobustScaler() X_scaled scaler.fit_transform(X) # 随机森林带类别权重 rf RandomForestClassifier( n_estimators300, max_depth8, min_samples_leaf3, class_weightbalanced, random_state42 ) # 分层交叉验证 cv StratifiedKFold(n_splits5, shuffleTrue, random_state42) y_pred cross_val_predict(rf, X_scaled, y, cvcv) print(classification_report(y, y_pred)) print(confusion_matrix(y, y_pred)) # 特征重要性 rf.fit(X_scaled, y) importance pd.Series(rf.feature_importances_, indexfeature_cols).sort_values(ascendingFalse) print(importance)逻辑说明先做缺失值剔除DGA 数据里气体列缺失的样本通常无法用均值填充因为缺失可能意味着未检测。衍生特征里 total_hydrocarbon 是总烃C2H4_ratio 和 C2H2_ratio 反映故障类型倾向CO2_CO_ratio 辅助判断绝缘纸状态。随机森林的 max_depth 设 8 是为了防止过拟合min_samples_leaf 设 3 保证叶子节点有足够样本。交叉验证用 StratifiedKFold 保持类别比例。特征重要性输出能告诉你哪些气体对分类贡献大通常乙炔和乙烯会排前面。参数说明n_estimators300是精度和速度的折中样本量小可以降到 100。max_depth根据样本量调整样本少于 500 时设 5 到 6。class_weightbalanced处理不平衡如果类别已经均衡可以去掉。random_state固定后结果可复现。5.2 结果怎么看混淆矩阵和特征重要性的解读分类报告里重点看 macro avg 的 f1-score因为类别不平衡时 accuracy 会虚高。混淆矩阵能看出哪些类别容易被混淆比如低温过热和中温过热经常互相误判因为它们的产气特征重叠。特征重要性里如果 CO2 排最后说明它对当前标签体系贡献小可以考虑去掉。如果 H2 重要性异常高检查是不是 H2 的量纲和其他气体差太多标准化没做好。5.3 一个容易忽略的验证按设备分组划分数据集如果数据里有一列设备 ID不要随机划分训练集和测试集。同一台设备的不同时间样本高度相关随机划分会导致测试集信息泄漏准确率虚高。正确做法是按设备 ID 分组用 GroupKFold。这个细节在论文里经常被忽略但在工程落地时是致命的。我一般会在数据体检阶段就检查有没有设备 ID 列有的话优先用分组划分。5.4 从基线到落地阈值调整和在线更新基线模型跑通后实际部署时还要做两件事。一是调整分类阈值比如把「电弧放电」的召回率调到 0.95 以上宁可误报不可漏报因为漏掉一个电弧放电样本可能导致设备损坏。二是设计在线更新机制新样本积累到一定数量后重新训练但要用时间序列划分验证确保模型没有退化。DGA 数据的分布会随设备老化缓慢漂移固定模型半年后性能下降是常态。我自己的习惯是每次拿到新的 DGA 数据包先花二十分钟做字段体检和标签分布再决定是直接查表还是训练模型。这个顺序反过来后面返工的时间会多得多。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

fiji-win64 安装、宏脚本与插件管理:ImageJ 生物图像分析实战指南

fiji-win64 安装、宏脚本与插件管理:ImageJ 生物图像分析实战指南

简介:Fiji(ImageJ)是一个面向 Windows 六十四位系统的免安装图像处理软件,专门服务于科研和医学图像分析用户。解压后不需要安装即可运行,能够直接读取 Raw 格式原始数据,对八位以上的高动态范围图像支持良…

2026/10/13 17:32:45 阅读更多 →
DeepSeek V4.1 Flash:低延迟大模型推理引擎实战解析

DeepSeek V4.1 Flash:低延迟大模型推理引擎实战解析

1. 项目概述:这不是一次常规升级,而是一次“响应速度革命”最近在多个技术社区和开发者群聊里,几乎每天都能刷到类似这样的消息:“DeepSeek V4.1 Flash 内测开了”“Flash 版推理延迟压到 87ms”“实测比上一代 V4 Pro 在长文本场…

2026/10/13 17:32:45 阅读更多 →
SpringBoot多数据源读写分离实战:从配置到高可用路由

SpringBoot多数据源读写分离实战:从配置到高可用路由

1. 为什么多数据源不是“加个配置就行”的事——从一次线上慢查询告警说起“SpringBoot配置多数据源”这个标题,听起来像教科书里的一个练习题:改几行yml,贴几段代码,跑通就完事。但我在某电商中台项目里连续踩了三个月的坑之后才…

2026/10/13 17:32:45 阅读更多 →

最新新闻

MuAsk:离线桌面级Text2SQL工具实战指南

MuAsk:离线桌面级Text2SQL工具实战指南

1. 项目概述:为什么一个桌面级 Text2SQL 工具值得你花十分钟装上试试?“沐问 MuAsk”这四个字刚出现在我 GitHub Star 列表里时,我第一反应是——又一个披着中文外衣的 LLM 前端?点开仓库主页,看到PySide6SQLite本地模…

2026/10/13 18:15:04 阅读更多 →
Cesium地形高度获取实战:从屏幕拾取到服务端批量算高全方案解析

Cesium地形高度获取实战:从屏幕拾取到服务端批量算高全方案解析

做三维 GIS 的朋友应该都有过这种经历:地图上有一个点,或者一串经纬度坐标,领导扔过来一句“把这片区域每个格子的地形高度都给我算出来”,或者产品经理说“鼠标挪过去就显示当前位置的海拔”。你以为在 Cesium 里调一个 API 就完…

2026/10/13 18:15:04 阅读更多 →
基于Xilinx 7系列的pcie以太网卡demo

基于Xilinx 7系列的pcie以太网卡demo

demo综述 1、本demo基于xc7a35tfgg484芯片,pcie部分使用axi memory mapped to pci express,外挂vivado自带的axi dma,网卡mac模块移植开源的eth,实现一个千兆带宽的pcie网卡。 2、工程结构如下3、demo整体框图 ┌────────…

2026/10/13 18:15:04 阅读更多 →
漏洞挖掘----基础配置Ai工具<二>

漏洞挖掘----基础配置Ai工具<二>

< 一 >Ai/mcp思维:1. Ai 是大脑&#xff1a;负责目标&#xff0c;拆解任务&#xff0c;生成测试思路2. 工具&#xff1a;浏览器&#xff0c;BP&#xff0c;插件&#xff0c;脚本&#xff0c;文件&#xff0c;&#xff0c;&#xff0c;负责真实操作&#xff0c;返回证据…

2026/10/13 18:15:04 阅读更多 →
R语言信贷风控建模:Prosper贷款数据的特征工程与可解释性实践

R语言信贷风控建模:Prosper贷款数据的特征工程与可解释性实践

1. 项目概述&#xff1a;这不是一次普通的R语言练习&#xff0c;而是一场对真实信贷行为逻辑的深度解剖Prosper平台是美国较早一批面向个人投资者与借款人的P2P借贷市场&#xff0c;其公开数据集&#xff08;Prosper Loan Data&#xff09;长期被全球高校金融课程、数据科学竞赛…

2026/10/13 18:15:04 阅读更多 →
MySQL 8.0 管理员实战:从安装到调优的完整指南

MySQL 8.0 管理员实战:从安装到调优的完整指南

简介&#xff1a;这份《MySQL 8.0 for Database Administrators Student Guide》是 Oracle University 官方推出的数据库管理员培训教材&#xff0c;面向正在学习或备考 MySQL 认证的 DBA、运维工程师及数据库方向学生&#xff0c;帮助系统掌握 MySQL 8.0 的安装配置、表设计、…

2026/10/13 18:13:58 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目&#xff0c;我最大的感受是&#xff0c;大部分坑不是出在技术前沿&#xff0c;而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节&#xff0c;最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了&#xff0c;很难不碰到舵机控制这道坎。做智能小车要转方向&#xff0c;做机械臂要抬关节&#xff0c;做云台要偏航俯仰&#xff0c;背后都是同一个东西在干活&#xff1a;舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”&#xff1f;——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台&#xff1f;或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜&#xff1f;又或者&#xff0c;在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →