WSL 下 CPU 版 Caffe 与 Faster R-CNN 环境搭建实战
1. 为什么要在 WSL 里折腾 CPU 版 Caffe 和 Faster R-CNN先把场景说清楚。你手里大概率是一台 Windows 笔记本或者台式机显卡要么是核显要么是 N 卡但驱动环境不想动总之短期内不打算碰 CUDA。可你又想跑通一个经典的目标检测流程比如 Faster R-CNN用来做数据集验证、算法复现或者课程作业。这时候最省事的路径就是在 WSLWindows Subsystem for Linux里装一个 Linux 发行版然后在里面用 conda 建一个隔离环境把 Caffe 编译成纯 CPU 版本再跑 Faster R-CNN 的 demo 或者训练。这条路听起来绕其实逻辑很顺。Caffe 这个框架虽然年头久了但它的 Faster R-CNN 实现尤其是早期那套 py-faster-rcnn在工业界和学术界被引用得非常多很多老项目的权重和配置文件都是围绕它写的。你想复现一个检测结果绕不开它。而 Windows 原生编译 Caffe 是出了名的痛苦依赖库版本、编译器、Python 绑定各种坑。WSL 提供了一个几乎原生的 Linux 环境apt 装依赖、make 编译、conda 管 Python 包整套流程和你在 Ubuntu 服务器上操作几乎一样省心太多。CPU 版本的意义在于不需要显卡不需要装 CUDA 和 cuDNN编译时间短环境体积小。代价是推理和训练速度慢但对于小规模验证、单张图片测试、理解网络结构来说完全够用。我实测下来一张 500x375 左右的图片CPU 上前向推理大概几秒到十几秒取决于你的 CPU 核心数和是否开了多线程。训练就别想了除非你愿意等几天。这篇文章适合谁看如果你是刚接触深度学习框架、想在本地跑通一个检测流程的学生或者转行者或者你手头只有一台普通办公本想验证一个老项目的效果那这篇内容就是给你写的。我会把从 WSL 安装、conda 环境配置、Caffe 编译、到 Faster R-CNN 跑通的完整链路拆开讲包括我踩过的坑和参数选择理由。你照着做大概率能省下好几个晚上的调试时间。2. 环境整体设计与方案选型思路2.1 为什么选 WSL 而不是虚拟机或双系统虚拟机跑深度学习框架最大的问题是 CPU 指令集透传和内存分配。VMware 或者 VirtualBox 里即使你分配了 8 核实际性能损耗也不小而且嵌套虚拟化有时候会出奇怪的问题。双系统倒是原生性能但切换麻烦你不可能为了跑个 demo 重启电脑。WSL2 的本质是一个轻量级虚拟机但微软做了深度集成文件系统互通、网络共享、终端直接调用用起来几乎感觉不到边界。更重要的是WSL2 的内核是真正的 Linux 内核apt、make、gcc 这些工具链完整编译 Caffe 不会遇到 Windows 下那种路径分隔符和库缺失的破事。2.2 为什么用 conda 而不是系统 Python 或 venvCaffe 的 Python 接口对版本极其敏感。它依赖 protobuf、numpy、boost 等一堆库而且老版本的 py-faster-rcnn 通常要求 Python 2.7 或者 Python 3.5 左右。你系统自带的 Python 版本很可能太新直接 pip 装依赖会各种冲突。conda 的好处是它能创建一个完全隔离的环境连 Python 解释器本身都是独立的你可以在里面装任意版本的 Python 和库不影响系统环境。而且 conda 的包管理对科学计算库的支持很好numpy、scipy 这些都有预编译版本省去编译时间。2.3 CPU 版 Caffe 的编译取舍Caffe 的编译选项里CPU_ONLY : 1是核心。开了这个Makefile 就不会去找 CUDA 和 cuDNN编译出来的库只依赖 CPU 和 BLAS。BLAS 的选择上我建议用 OpenBLAS它在 CPU 上的矩阵运算优化做得不错而且 apt 直接装比 Atlas 省事。如果你追求极致性能可以编译 MKL但那个流程更复杂对普通验证来说没必要。另外USE_OPENCV和USE_LEVELDB、USE_LMDB这些要打开因为 Faster R-CNN 的数据读取依赖它们。Python 层要打开WITH_PYTHON_LAYER因为 py-faster-rcnn 用了自定义的 Python 层。2.4 版本匹配的坑这是最容易翻车的地方。Caffe 的 master 分支和 py-faster-rcnn 的代码有时候不兼容因为后者依赖一些旧的 API。我建议直接用 py-faster-rcnn 官方仓库里推荐的 Caffe 版本或者用社区维护的兼容分支。Python 版本上如果你用 Python 3需要改一些 print 语句和除法py-faster-rcnn 原始代码是 Python 2 的。省事的做法是直接用 Python 2.7 的 conda 环境虽然老但能跑通少改代码。如果你坚持用 Python 3那就准备好改几处语法和库调用。3. WSL 与基础依赖的安装实操3.1 开启 WSL 并安装 Ubuntu在 Windows 搜索栏输入“启用或关闭 Windows 功能”勾选“适用于 Linux 的 Windows 子系统”和“虚拟机平台”。重启后打开 PowerShell输入wsl --install默认会装 Ubuntu 的最新 LTS 版本。如果你想要指定版本可以用wsl --install -d Ubuntu-20.04。装完后设置用户名和密码这个密码在后面 sudo 的时候要用。注意WSL2 需要 Windows 10 版本 2004 以上或者 Windows 11。如果你的是老版本先升级系统。装完后建议把 WSL 的默认版本设为 2wsl --set-default-version 2。然后进去更新一下包列表sudo apt update sudo apt upgrade -y。这个过程可能有点慢取决于你的网络。3.2 安装编译工具链和基础库Caffe 编译需要一堆开发库。下面这条命令是我实测下来比较全的依赖列表你可以直接复制sudo apt install -y build-essential cmake git pkg-config libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler libgflags-dev libgoogle-glog-dev liblmdb-dev libatlas-base-dev libopenblas-dev python-dev python-numpy python-pip如果你用 Python 3把python-dev换成python3-devpython-numpy换成python3-numpypython-pip换成python3-pip。另外libboost-all-dev也建议装上虽然有些教程说不需要但 py-faster-rcnn 的某些依赖会用到 boost 的 Python 绑定。提示libopencv-dev装的是 OpenCV 3.x 或 4.xCaffe 对 OpenCV 4 的支持需要改一些代码如果你遇到编译错误可以考虑装 OpenCV 3.4但 apt 源里不一定有。省事的办法是用 OpenCV 4然后根据报错改几处头文件引用。3.3 安装 conda 并创建环境在 WSL 里装 Miniconda 比 Anaconda 轻量。下载安装脚本wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh一路回车最后问你是否初始化 shell选 yes。然后source ~/.bashrc让 conda 生效。接着创建环境conda create -n caffe-cpu python2.7 conda activate caffe-cpu如果你用 Python 3把python2.7改成python3.6或3.7别用太新的版本Caffe 的 Python 绑定对 3.8 以上支持不好。环境建好后装一些 Python 依赖pip install numpy protobuf3.20.3 scikit-image matplotlib opencv-pythonprotobuf 的版本要特别注意Caffe 编译时用的 protobuf 版本和 Python 里装的版本要一致否则 import caffe 会报错。我一般用 3.20.3比较稳。4. 编译 CPU 版 Caffe 的核心步骤4.1 获取 Caffe 源码并配置 Makefile.config从 GitHub 克隆 Caffegit clone https://github.com/BVLC/caffe.git cd caffe cp Makefile.config.example Makefile.config然后编辑Makefile.config下面这几处是关键CPU_ONLY : 1 USE_OPENCV : 1 USE_LEVELDB : 1 USE_LMDB : 1 WITH_PYTHON_LAYER : 1 BLAS : open如果你用 Python 2.7PYTHON_INCLUDE和PYTHON_LIB那几行要指向 conda 环境里的路径。用python -c import sys; print(sys.prefix)可以查到环境路径。比如PYTHON_INCLUDE : $(HOME)/miniconda3/envs/caffe-cpu/include/python2.7 \ $(HOME)/miniconda3/envs/caffe-cpu/lib/python2.7/site-packages/numpy/core/include PYTHON_LIB : $(HOME)/miniconda3/envs/caffe-cpu/lib另外INCLUDE_DIRS和LIBRARY_DIRS里要加上 hdf5 的路径因为 Ubuntu 新版里 hdf5 的路径变了INCLUDE_DIRS : $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial LIBRARY_DIRS : $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial注意如果你用的是 OpenCV 4可能需要在Makefile.config里加-DOPENCV_VERSION4或者在代码里改具体看报错。4.2 修改 Makefile 里的链接库名称Ubuntu 新版里 hdf5 的库文件名带版本号直接 make 会找不到-lhdf5。编辑Makefile找到LIBRARIES那几行把-lhdf5改成-lhdf5_serial-lhdf5_hl改成-lhdf5_serial_hl。这个改动在Makefile和Makefile.config里都可能需要看你的版本。4.3 开始编译先编译基础库make all -j$(nproc)-j$(nproc)是用满所有 CPU 核心加快编译。这个过程大概十几分钟到半小时取决于你的机器。如果报错通常是依赖缺失或者路径不对根据错误信息逐个解决。编译完基础库后编译测试和 Python 接口make test -j$(nproc) make pycaffe -j$(nproc)make test可能会报一些测试用例失败但不影响使用可以跳过。make pycaffe成功后把 Caffe 的 Python 路径加到环境变量export PYTHONPATH$PYTHONPATH:$(pwd)/python你可以把这行加到~/.bashrc里免得每次都要设。4.4 验证 Caffe 是否可用进入 Python 环境输入import caffe print(caffe.__version__)如果没报错说明 Caffe 的 Python 接口通了。如果报ImportError: libcaffe.so找不到检查LD_LIBRARY_PATH是否包含了 Caffe 的build/lib目录。可以这样设export LD_LIBRARY_PATH$LD_LIBRARY_PATH:$(pwd)/build/lib5. 跑通 Faster R-CNN 的完整流程5.1 获取 py-faster-rcnn 代码和模型克隆仓库git clone https://github.com/rbgirshick/py-faster-rcnn.git cd py-faster-rcnn这个仓库里有个caffe-fast-rcnn子目录是它依赖的 Caffe 版本。你可以直接用这个版本编译而不是用刚才的 BVLC/caffe。编译步骤和上面一样改Makefile.config和Makefile然后make all -j$(nproc)和make pycaffe。提示caffe-fast-rcnn的代码比较老对 OpenCV 4 和 protobuf 新版本兼容性差。如果你用刚才编译的 BVLC/caffe需要把py-faster-rcnn/lib里的 Python 文件里的caffe引用指向你的 Caffe 路径。省事的做法是直接用caffe-fast-rcnn然后按上面的方法改配置。5.2 下载预训练模型Faster R-CNN 的 demo 需要预训练模型。官方提供了 VGG16 和 ZF 两个版本。VGG16 精度高但慢ZF 快但精度低。CPU 上建议用 ZF因为 VGG16 在 CPU 上前向一次可能要几十秒。下载脚本在data/scripts/fetch_faster_rcnn_models.sh运行它cd data/scripts ./fetch_faster_rcnn_models.sh如果下载慢可以手动找镜像但注意模型文件要放到data/faster_rcnn_models/目录下。5.3 编译 Cython 模块py-faster-rcnn 的lib目录下有一些 Cython 模块需要编译cd lib make如果报错numpy/arrayobject.h找不到说明 Python 的 numpy 头文件路径没设对。可以在Makefile里加PYTHON_INCLUDE : $(HOME)/miniconda3/envs/caffe-cpu/lib/python2.7/site-packages/numpy/core/include5.4 运行 demo回到py-faster-rcnn根目录运行./tools/demo.py --net zf如果一切正常你会看到它加载模型然后对data/demo/里的图片进行检测输出带框的图片。CPU 上这个过程可能需要几十秒到几分钟耐心等。注意如果报AttributeError: module object has no attribute text_format说明 protobuf 版本不匹配。降低 protobuf 版本到 3.20.3 或者更低重新编译 Caffe。6. 常见问题与排查技巧实录6.1 编译阶段常见错误错误信息原因解决方法fatal error: hdf5.h: No such filehdf5 头文件路径不对在Makefile.config的INCLUDE_DIRS加/usr/include/hdf5/serialcannot find -lhdf5库文件名带版本号在Makefile里把-lhdf5改成-lhdf5_serialundefined reference to cv::imreadOpenCV 链接问题确认USE_OPENCV : 1并检查LIBRARY_DIRS是否包含 OpenCV 库路径Python.h: No such filePython 开发头文件缺失装python-dev或python3-dev并检查PYTHON_INCLUDE路径protobuf相关错误protobuf 版本不匹配统一 conda 环境和编译时用的 protobuf 版本6.2 运行阶段常见错误错误信息原因解决方法ImportError: No module named caffePYTHONPATH 没设把 Caffe 的python目录加到PYTHONPATHImportError: libcaffe.so动态库路径没设把build/lib加到LD_LIBRARY_PATHAttributeError: module object has no attribute text_formatprotobuf 版本太新降级 protobuf 到 3.20.3 并重新编译TypeError: numpy.float64 object cannot be interpreted as an indexnumpy 版本太新降级 numpy 到 1.16 左右KeyError: max_overlaps代码和模型不匹配确认用的是caffe-fast-rcnn里的 Caffe而不是 BVLC/caffe6.3 独家避坑技巧第一个技巧编译前先make clean再make all。有时候改了配置不 clean旧的 object 文件会导致奇怪的链接错误。第二个技巧如果你在 WSL 里编译内存不够会卡死。WSL2 默认最多用主机一半内存你可以在用户目录下建.wslconfig文件限制内存和 CPU[wsl2] memory8GB processors4第三个技巧CPU 版跑 demo 时可以设OMP_NUM_THREADS环境变量来限制线程数避免占满所有核心导致系统卡顿export OMP_NUM_THREADS4第四个技巧如果make pycaffe报fatal error: numpy/arrayobject.h在Makefile.config里把 numpy 的 include 路径写对用python -c import numpy; print(numpy.get_include())查。7. 性能调优与后续扩展建议7.1 CPU 推理速度优化CPU 上跑 Faster R-CNN速度是最大的痛点。几个可以尝试的优化方向一是用 OpenBLAS 并设置线程数OPENBLAS_NUM_THREADS4二是把输入图片分辨率调小比如从 600 调到 400速度会明显提升但小目标检测精度会下降三是用 ZF 网络而不是 VGG16参数量少很多速度快几倍。如果你只是验证流程ZF 足够了。7.2 从 demo 到自定义数据跑通 demo 后你可能会想用自己的图片测试。把图片放到data/demo/目录下重新运行demo.py即可。如果想训练自己的数据那就复杂了需要准备 VOC 格式的数据集改pascal_voc.py里的类别然后跑train_net.py。CPU 训练基本不可行建议至少用一块入门级显卡。7.3 替代方案思考说实话如果你不是非要用 Caffe 不可现在有更好的选择。PyTorch 版本的 Faster R-CNNtorchvision 里自带在 CPU 上也能跑安装简单得多pip install torch torchvision就行不用编译。但如果你面对的是一个老项目权重和配置文件都是 Caffe 格式的那还是得走这条路。我个人的经验是Caffe 的环境一旦配好后面就省事了配的过程虽然烦但值得。最后分享一个小技巧把整个 conda 环境打包备份下次换机器直接恢复省得重新编译。conda env export environment.yml然后在新机器上conda env create -f environment.yml。不过 Caffe 的编译产物不在 conda 环境里你得把整个 Caffe 目录也拷过去或者重新编译。

相关新闻

三种手眼标定方法实战对比:AX=XB、非线性优化与FOE

三种手眼标定方法实战对比:AX=XB、非线性优化与FOE

简介:这份PDF资料聚焦机器人视觉中的手眼标定技术,面向计算机视觉、双目视觉与机器人抓取方向的学习者和研究者,系统讲解末端执行器与摄像头坐标系转换关系的求解思路。内容从Euler角、Rodrigues表示、Cayley表示及FOE点等基础知识切入&#…

2026/10/13 17:58:35 阅读更多 →
交换机端口镜像SPAN全解析:从原理到排障实战

交换机端口镜像SPAN全解析:从原理到排障实战

抓包可以说是网络工程师最常用的排查手段之一,但很多刚入行的朋友第一次遇到“端口镜像”这个概念时,都会卡在一个问题上:明明交换机上连着好几台设备,我把电脑接在交换机上,为什么用抓包工具就是看不到别的机器在跑什…

2026/10/13 17:58:35 阅读更多 →
图书管理系统课程设计:从E-R图到SQL Server存储过程的完整实践指南

图书管理系统课程设计:从E-R图到SQL Server存储过程的完整实践指南

简介:一份软件工程与数据库课程设计任务书,围绕“图书管理系统”展开完整数据库设计流程,适合高校计算机、软件工程专业学生作为课程设计参考。文档覆盖需求分析、概念结构设计(E-R图)、逻辑结构设计(关系模…

2026/10/13 17:58:35 阅读更多 →

最新新闻

光流法+CNN如何检测AI假视频?帧间运动一致性分析实战

光流法+CNN如何检测AI假视频?帧间运动一致性分析实战

1. 为什么光流法会成为假视频检测的破局点第一次读到把光流和卷积网络结合做假视频检测这个思路时,我的反应是"这角度够刁钻"。大多数人做视频真伪识别,第一反应都是盯着单帧画面找瑕疵——像素级伪影、边缘模糊、色彩断层。但假视频的本质问题…

2026/10/13 18:35:38 阅读更多 →
D2D通信MATLAB仿真从入门到实战:接入模式与资源分配算法解析

D2D通信MATLAB仿真从入门到实战:接入模式与资源分配算法解析

简介:面向5G网络中的D2D(设备到设备)通信研究,这份资源提供了完整的优化、仿真与接入模式选择MATLAB实现,适合通信专业研究人员、算法工程师及相关专业学生用于算法验证与性能分析。包内共21个文件,其中20个…

2026/10/13 18:35:38 阅读更多 →
Vue项目部署全攻略:从打包到Nginx配置与故障排查

Vue项目部署全攻略:从打包到Nginx配置与故障排查

本地跑得好好的,代码一上服务器就白屏?F12 打开一看全是 404 资源报错?如果你正在经历这个阶段,恭喜你,你到了 Vue 学习路上最“让人长记性”的一关——项目部署。这篇内容对应进阶学习的第 58 天,刚好是 V…

2026/10/13 18:35:38 阅读更多 →
HHO优化TV图像修复:基于Matlab的自动参数寻优实现

HHO优化TV图像修复:基于Matlab的自动参数寻优实现

先说说我为什么盯上这个方向。做图像修复实验的同学应该都有过这种经历:TV(Total Variation,全变分)修复模型效果确实能打,边缘保持是它祖传的看家本领,但那个正则化参数λ一旦靠手试,整个实验就…

2026/10/13 18:35:38 阅读更多 →
HarmonyOS 6相机拍照与相册选图实战:从权限申请到PixelMap优化

HarmonyOS 6相机拍照与相册选图实战:从权限申请到PixelMap优化

1. 项目概述与场景价值鸿蒙系统发展到 HarmonyOS 6 这个阶段,应用开发早已不是"能用就行"的逻辑,而是讲究一次开发、多端适配、体验一致。这次分享的相机拍照和相册选图实战项目,表面上看只是两个最常见的系统能力调用,…

2026/10/13 18:35:38 阅读更多 →
pstack安装指南:从gdb依赖到无root部署的完整路径

pstack安装指南:从gdb依赖到无root部署的完整路径

1. 为什么一个“看堆栈”的小工具,值得单独写一篇安装指南?很多人第一次看到pstack这个名字,会下意识觉得:“不就是个 Linux 下查进程调用栈的命令吗?apt install pstack或者yum install pstack一行搞定,还…

2026/10/13 18:34:36 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

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

周新闻

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

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

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

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

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

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

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

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

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