news 2026/9/24 9:55:57

自托管RSS阅读器FreshRSS:用Docker十分钟搭建独立信息入口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
自托管RSS阅读器FreshRSS:用Docker十分钟搭建独立信息入口

这几年的资讯消费,说实话是越来越让人心累了。不管打开哪个App,都是算法替你决定今天该看什么。刷了一小时,回头一看全是同类内容,真正想看的反而被淹没在信息洪流里。我也是在某个深夜翻完一个又一个信息流之后,萌生了一个念头:把阅读这件事重新握在自己手里。于是就有了今天要聊的主角——FreshRSS,一个可以自托管、数据完全属于你自己的RSS阅读器。这篇博文我会从部署思路、Docker实践、日常使用到问题排查,完整走一遍,保证你跟着操作,十分钟内也能拥有一个独立的阅读入口,彻底告别“推荐什么看什么”的被动状态。

我最早用RSS还是Google Reader的年代,那时候订阅、分类、标记已读,清爽得不行。后来Google Reader关停,整个RSS生态经历了一段沉寂期,很多朋友转向了今日头条、微信公众号这类内容聚合平台,我也一样。但时间长了你会发现,算法推荐本质上是在“驯化”你的注意力:它不断猜测你喜欢什么,然后只让你看到那些内容。这种模式不是不好,而是不适合所有人。如果你是想认真做信息输入的创作者、研究者、或者纯粹想保持独立思考的读者,RSS的价值会重新浮现。

FreshRSS就是其中一个特别适合自部署的项目。它本身是PHP写的,开源、轻量、支持多用户,底层可以跑SQLite也可以跑MySQL。界面干净,功能不花哨但够用,最关键的是它提供一个兼容Google Reader的API,手机上可以搭配Reeder、FeedMe这类第三方客户端使用。换句话说,搭建好之后,你不仅在电脑上能看,手机上也能随时同步,体验完全不输给商业服务。

这次我用的部署方案是Docker Compose,这也是目前自托管服务最主流的玩法。后面我会把整套配置、步骤、踩过的坑全部展开说清楚,包括那些官方文档里没写明白的细节。不管你是第一次接触Docker还是已经玩过一段时间,看完这篇都能顺利跑起来。

1. 为什么自建RSS阅读器?FreshRSS在众多方案里的定位

1.1 算法推荐与RSS的本质差异

先聊一个核心问题:算法推荐和RSS到底差在哪?

算法推荐的工作方式是“收集你的行为数据→建立用户画像→筛选内容→推送给用户”。它的目标不是让你看到更全面的世界,而是让你在App里待得更久。所以你刷到的内容高度同质化,观点越来越趋同,你以为自己在“获取信息”,其实是在不断验证自己已有的认知。时间久了,人会变得信息偏食。

RSS的机制完全反过来:你主动选择信息源,你决定订阅谁、不订阅谁,阅读器只负责把订阅源的新内容抓取回来,按时间顺序排好。没有猜你喜欢,没有千人千面,没有“划掉一个又出现一个”的推荐流。你要做的只是定期打开阅读器,把没看的内容看完,或者直接标记全部已读。这种阅读方式,天然就是对抗算法焦虑的。

当然,RSS不适合所有人。它要求你有一点信息来源管理的意识,需要你偶尔花点时间维护订阅列表。但对于写博客的人、靠信息吃饭的运营、做技术调研的工程师,或者单纯厌倦推荐流的普通读者,RSS依然是目前最可靠的信息获取方案。FreshRSS的意义,就是把这个方案变成一个完全由你掌控的私有服务。

1.2 FreshRSS与主流自托管阅读器对比

自托管RSS阅读器其实有好几个选择,除了FreshRSS,常见的还有Miniflux、Tiny Tiny RSS(TT-RSS)、Stringer等。我最终选了FreshRSS,原因可以看下面这张表格:

对比维度FreshRSSMinifluxTiny Tiny RSS
开发语言PHPGoPHP
安装复杂度低,容器镜像完善低,单二进制文件中,依赖较多
资源占用较低(需PHP-FPM)极低中等
多用户支持支持不支持支持
API兼容Google Reader APIFever API自己的API
移动端生态Reeder、FeedMe等官方客户端、Reeder官方App为主
UI风格传统但可定制极简极客风传统
扩展机制有官方扩展仓库少量内置扩展有插件机制

Miniflux我很喜欢它的轻量和极简风格,但它是单用户设计,而且没有官方移动客户端,想在手机上看还得通过浏览器或者第三方渠道,比较折腾。Tiny Tiny RSS功能确实丰富,但历史包袱重、部署依赖多,Docker方案也没FreshRSS清爽。FreshRSS是三者里平衡点最好的:部署足够简单,默认就带API,手机客户端直接支持,扩展机制也成熟,可以作为长期主力方案。

另外一个选FreshRSS的原因是它的社区非常活跃。项目在GitHub上常年保持更新,官方镜像发布频率也很高,安全漏洞修复及时。自托管服务最怕作者弃坑,FreshRSS在这一点上让人放心。

2. 部署前的准备:方案选型与运行环境

2.1 为什么选择Docker Compose部署

FreshRSS的官方文档提供了两种主要安装方式:传统方式需要LNMP环境(Linux + Nginx + MySQL/MariaDB + PHP),得手动装PHP扩展、配Nginx站点、创建数据库,流程繁琐还容易踩坑;Docker方式把整个运行环境打包进镜像,拉下来就能跑,省去了大量环境配置的重复劳动。

我强烈建议走Docker Compose这条路。原因有三点:

第一,可复现性。你把docker-compose.yml文件保存好,以后无论换服务器还是重新部署,只要一份配置文件就能恢复整套服务,不用再去回忆当初“那个PHP扩展到底装没装”。

第二,隔离干净。FreshRSS跑在容器里,不会污染宿主机的系统环境。你今天部署FreshRSS,明天再跑一个Nginx或数据库,互不干扰。

第三,升级方便。镜像发布新版本后,docker compose pull && docker compose up -d两条命令完成升级。如果是传统环境,你得手动备份、替换文件、检查扩展兼容性,费时费力。

不过Docker部署也有个容易被忽视的前提:你的服务器最好有1GB以上内存,512MB以下内存跑FreshRSS会有点吃力,尤其是PHP-FPM进程同时处理抓取任务时。1核2G的入门级云主机跑FreshRSS完全够用,我自己的部署环境就是这样一个“小水管”配置,跑得很稳。

2.2 需要准备哪些基础环境

开始之前,确认这几样东西你已经准备好:

  • 一台可公网访问的服务器,操作系统不限,Ubuntu 22.04/Debian 12/CentOS 7都可以
  • 一个域名,非必需但强烈建议,后续配HTTPS、手机客户端连接都需要(用IP也能跑,但体验和安全性差一截)
  • Docker Engine和Docker Compose插件,这是最核心的依赖
  • 一个趁手的终端工具,SSH连上服务器用

服务器购买这里不多展开,选一个你用得顺手的云厂商就好。域名的话,建议用便宜一点的.xyz或.top后缀,反正只是自用,没必要花大价钱。

Docker的安装可以参考官方脚本,也可以直接用发行版自带的软件源安装。装完之后记得验证一下版本:

docker --version docker compose version

如果docker compose提示命令不存在,可能是Docker版本较旧,需要安装docker-compose-plugin,或者直接用老款的docker-compose命令。后面我提供的配置都以新版docker compose(中间带空格)为准。

2.3 数据存储选SQLite还是MySQL

FreshRSS支持两种数据库:SQLite和MySQL/MariaDB。不少新手在这一步犹豫,我直接给结论:单用户或者两三个人自用,选SQLite就够了;需要多人同时使用、追求高并发写入性能,才考虑MySQL。

SQLite的好处是零配置,数据就是一个文件,备份直接复制文件就行。FreshRSS官方镜像默认就用SQLite存数据,启动后自动初始化,不需要额外起一个数据库容器。缺点是不适合高频并发写入,但个人使用场景根本到不了那个量级。

MySQL的好处是性能上限高、支持网络访问、便于搭建主从备份,但你必须单独跑一个MySQL容器,还要处理初始化账号、库、权限,复杂度明显上升。我后面会给出SQLite“极简版”和MySQL“完整版”两套dokcer-compose配置,你按需选择。

3. FreshRSS一键部署实操:从拉镜像到初始化完成

3.1 极简版:SQLite + FreshRSS单容器

先上一个最简配置,适合想快速体验的朋友。在服务器上创建一个目录,比如/opt/freshrss,然后新建docker-compose.yml文件,内容如下:

services: freshrss: image: freshrss/freshrss:latest container_name: freshrss hostname: freshrss restart: unless-stopped ports: - "8080:80" environment: TZ: Asia/Shanghai CRON_MIN: '*/15 * * * *' TRUSTED_PROXY: 127.0.0.1 volumes: - ./data:/var/www/FreshRSS/data - ./extensions:/var/www/FreshRSS/extensions

说几个关键配置项:

image我直接用latest标签,这是官方推荐的日常使用标签,会跟随最新稳定版更新。如果你追求极致稳定,也可以固定一个具体版本号,比如freshrss/freshrss:1.24.1,但升级时需要手动改标签,稍微麻烦一点。

CRON_MIN这个环境变量很关键。FreshRSS需要定时去订阅源抓取新内容,容器内置了一个cron调度器,*/15 * * * *表示每15分钟刷新一次订阅。如果你订阅的源更新频繁,可以改成*/5 * * * *,但别太频繁,否则容易触发部分网站的抓取频率限制。

/var/www/FreshRSS/data/var/www/FreshRSS/extensions是数据目录和扩展目录,必须挂载到宿主机。这是整个部署中最核心的部分:以后你的订阅数据、数据库文件、用户配置都在宿主机./data下,容器挂了数据也不会丢。

启动之前,先把宿主机目录权限准备好:

mkdir -p data extensions chmod -R 777 data extensions

FreshRSS容器内的PHP-FPM进程默认以www-data用户运行,UID是33,和宿主机用户的UID大概率不一致。如果不给data和extensions目录足够权限,容器创建数据库时会报权限错误。用777权限是偷懒做法,但胜在省事,个人服务器上问题不大。更优雅的方案是chown -R 33:33 data extensions,但不同环境下UID可能不同,所以我更推荐用777,实测稳定。

一切都准备好之后,直接:

docker compose up -d docker compose logs -f

看到日志里出现类似Finished startup或者Nginx/PHP-FPM相关的启动信息,说明容器已经起来了。这时候浏览器访问http://你的服务器IP:8080,就能看到FreshRSS的安装页面。

3.2 初始化向导的完整流程

看到FreshRSS安装界面后,流程非常简单,但有几个细节值得注意。

第一步是选择语言,默认有中文界面。第二步是设置管理员账号:用户名、密码、邮箱,途中会提示你选择数据库类型,如果你用的是3.1的极简配置,选SQLite就行。

有个容易让新手困惑的地方是“FreshRSS的URL地址”这一栏。如果是用IP+端口访问,就填http://你的IP:8080;如果已经配了域名,就填https://你的域名。这个地址会写入配置文件中,影响后续生成订阅链接和移动端连接,最好一次性填对,反悔了就得改数据库或者重新安装。

点击“安装”之后,FreshRSS会初始化数据库、创建管理员账号、写入配置文件,全程大概几秒钟。完成后会自动跳转到登录页,用刚创建的管理员账号登录,就能看到FreshRSS的主界面了。

第一次进入会有一个欢迎引导,提示你添加订阅。你可以先随便添加一个博客或新闻站的RSS源试试抓取效果。比如很多技术博客都默认输出RSS,直接在“订阅管理”里输入站点地址,FreshRSS会自动尝试发现RSS地址,也可以直接粘贴完整的feed URL。

到这一步,一个能用的FreshRSS已经跑起来了。但离“手机上也顺滑阅读”还有一段距离,下面要解决访问入口和客户端连接的问题。

3.3 完整版:配合Nginx反向代理与HTTPS

直接用IP+端口访问虽然能用,但有几个问题:一是端口号不好记,二是没有HTTPS加密,三是部分RSS源对非标准端口的抓取请求不友好。所以只要你有域名,我都建议配一层反向代理。

反向代理的方式很多,Caddy是其中最省心的一个——它支持自动申请和续期HTTPS证书,配置文件也短。不过Nginx用户群体更大,网上资料丰富,这里我主要讲Nginx方案。

首先改docker-compose,把FreshRSS的端口从映射到宿主机改为仅内部访问,避免绕过Nginx直接暴露到公网。修改后的配置:

services: freshrss: image: freshrss/freshrss:latest container_name: freshrss hostname: freshrss restart: unless-stopped expose: - "80" environment: TZ: Asia/Shanghai CRON_MIN: '*/15 * * * *' TRUSTED_PROXY: 127.0.0.1 volumes: - ./data:/var/www/FreshRSS/data - ./extensions:/var/www/FreshRSS/extensions

注意这里的expose只对Docker内部网络开放,宿主机直接访问不到8080端口了,需要由Nginx转发到容器。同时把TRUSTED_PROXY改为127.0.0.1,告诉FreshRSS“信任来自反向代理的请求”,这样它才能正确判断用户真实IP,日志和会话管理都更准确。

然后宿主机安装Nginx,配置一个站点:

server { listen 80; server_name rss.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name rss.example.com; ssl_certificate /etc/nginx/cert/rss.example.com.pem; ssl_certificate_key /etc/nginx/cert/rss.example.com.key; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }

证书可以用Let's Encrypt自动申请,也可以用你云厂商的免费证书,正规流程是先用certbot生成证书再指向对应路径。这里我不展开证书签发细节,只提醒一句:证书到期前一定要设置自动续期,手动续期你迟早会忘。

配好Nginx之后,重启服务:

docker compose down docker compose up -d nginx -t && systemctl reload nginx

然后访问https://rss.example.com,如果一切正常,你会看到FreshRSS的登录界面,地址栏有小锁标志,说明HTTPS已经生效。

3.4 移动端连接:用Reeder和FeedMe实现随时随地阅读

电脑上阅读只是RSS的一半体验,手机上刷订阅才是真正的日常。FreshRSS的杀手锏就是兼容Google Reader API,这意味着大量第三方阅读器可以直接连过来。

iOS上我推荐Reeder 4,这算是RSS阅读器的老牌选手,界面简洁、手势操作顺手,支持FreshRSS的API接入。安卓上推荐FeedMe,免费开源,功能很全,尤其对FreshRSS的兼容性调教得很用心。

连接方法大同小异,以FeedMe为例:打开应用,选择“FreshRSS”类型,填写你的FreshRSS地址(比如https://rss.example.com/api/),再填用户名和密码,测试连接通过后就能同步所有订阅和未读状态。Reeder的添加方式稍微不同,需要手动选择“Google Reader API”类型,但原理一样。

这里有一个坑:如果你用的是IP访问,移动端连接大概率会失败,因为部分客户端强制要求HTTPS。这也是我反复强调“配置域名和HTTPS”的原因之一。另外,FeedMe里如果要推送通知,需要额外配置FreshRSS的扩展,这个后面再说。

4. 日常使用与进阶玩法:让FreshRSS真正成为阅读中枢

4.1 订阅源管理:导入、分类与统一管理

初始化完成之后,第一件事不是急着订阅,而是把已有的RSS源迁移过来。如果你之前用Feedly或者Inoreader这类在线服务,可以直接从那边导出OPML文件,然后在FreshRSS里导入。OPML是RSS阅读器的通用交换格式,一串XML,记录了你的订阅列表和分类结构。

导入路径在FreshRSS后台“订阅管理”里,上传OPML之后,分类和订阅会原样保留。我当初从Feedly导出再导入FreshRSS,整个过程不到一分钟,几百个订阅一个没漏。这个功能对迁移用户特别友好,基本没有迁移成本。

分类这件事,我建议做得克制一点。我见过有人建二十多个分类,最后阅读效率反而低。合理的分类策略是:按“用途”切分而非“领域”切分。比如“每日必读”(高频重点源)、“普读”(可看可不看)、“稍后读”(囤着不动)、“行业监控”(竞品动态)。这样打开阅读器,先看“每日必读”,看完再扫其他,哪怕几百上千个订阅也能轻松消化。

FreshRSS的标签(tag)系统也值得利用:一条订阅可以同时属于多个标签,比单一分类灵活。比如一个技术博客既打上“前端”标签又打上“每日必读”,在标签视图里就能交叉筛选。不过标签功能在移动端支持一般,主力还是分类。

4.2 提升抓取质量:全文抓取与内容清洗

RSS有一个让人头疼的历史问题:很多源默认只输出摘要,不输出全文。你明明订阅了,却只能在阅读器里看到开头两行话,想读全文还得点进原网站。在电脑端还行,手机上就非常难受了。

FreshRSS对这个问题有解决方案。官方扩展仓库里有一个扩展叫“全文抓取”(真正名称是freshrss_extensions里的Full text feed,也有其他第三方开源方案),安装后可以对所有订阅源启用全文抓取。原理是拿到摘要后,自动请求原文页面,再把正文内容提取出来显示在阅读器里。

启用方法:把扩展代码放进extensions目录,然后在后台“扩展管理”里启用即可。注意,全文抓取会显著增加服务器负载和带宽消耗,因为每次刷新都要额外抓取原文页面。如果你的VPS配置不高,建议只对真正只出摘要的源启用,别搞全局。

另外一个问题是噪音条目。有些源会定期发一些无关广告或者凑数内容,FreshRSS的过滤规则(即filter)可以自动把符合关键词的文章标记已读或隐藏。比如你在筛选规则里设置“标题包含‘促销’,则标记已读”,以后这类内容就不会打扰你了。

4.3 数据备份与迁移:数据是你的核心资产

自托管服务最重要的就是数据安全,RSS阅读器的数据主要指你的订阅列表、已读状态和用户配置。FreshRSS的数据都存在data目录里,SQLite模式下就是一个db.sqlite文件。

备份这个文件就够了。我写了个简单的cron任务,每天凌晨打包整个data目录并上传到对象存储,万一服务器挂了,新机器上一恢复,订阅和已读状态全都在。脚本不复杂,核心命令就一行:

tar czf freshrss-backup-$(date +%F).tar.gz -C /opt/freshrss data extensions

恢复时把压缩包解压回原目录,再docker compose up -d,完事儿。这里强调一点:不要只备份db.sqliteextensions目录里可能有你装的扩展配置,data目录下还有其他配置文件,整个目录一起打包最稳妥。

4.4 结合AI大模型:给RSS加一个“摘要大脑”

最近大家都在聊本地部署大模型,其实RSS阅读器和大模型的结合点很多。FreshRSS虽然没有内置AI功能,但它的API和扩展机制允许你接入外部服务。比如可以用FreshRSS的过滤钩子把每篇文章的标题和摘要发到本地部署的大模型接口,让模型生成一句话精华,再输出回阅读器。

我试过最简单的实现:写一个Python脚本,定时从FreshRSS API拉取未读文章,调用本地Ollama跑一个轻量模型做摘要,再把摘要存到一个单独的订阅源里。这样打开阅读器,先扫一眼AI摘要,觉得值得细读再点开全文。相当于给信息流加了一层“人工预筛”。

如果你也用Ollama这类本地推理工具,可以顺手研究下。不需要把摘要写回FreshRSS数据库,建一个子账号挂个自定义RSS源也能实现类似效果。思路不难,就是脚本做中转,关键是别把抓取频率设太高,免得把API打挂。

5. 常见问题与排查技巧实录

5.1 容器权限导致无法初始化数据库

这是我在各种部署群里看到最多的问题。现象是访问安装页面之后,点安装提示无法写入数据库,或者报Failed to create database。绝大多数是因为data目录的权限不对。

FreshRSS容器里的PHP进程以www-data用户运行,UID为33,而宿主机新建的目录默认归root所有。解决方法是把data和extensions目录的所有者改为33或者直接777:

chmod -R 777 /opt/freshrss/data /opt/freshrss/extensions

改完再重新执行一次docker compose up -d,然后刷新页面重试。注意,如果数据目录里已经存在损坏的初始化文件,建议清空data目录再装,否则可能会复现同样的问题。

5.2 定时刷新不生效

FreshRSS的CRON_MIN环境变量只设置了一个刷新周期,但容器里的cron服务默认被某些镜像精简了。如果你发现新文章很久都不出现,先看一下容器日志:

docker logs freshrss | grep cron

如果没有任何cron输出,说明定时任务没有跑起来。这时候可以试试在老版本镜像上改用宿主机cron的方式:定期执行docker exec freshrss php /var/www/FreshRSS/cli/actualize-user.php --user 你的用户名,手动触发抓取。不过新版本镜像一般没这个问题,我自己用latest标签一年多,刷新一直很准时。

5.3 部分订阅源抓取不到内容

遇到这种情况,第一步先确认源本身是否还能访问。RSS源“失联”是常态,好端端的站点可能突然关闭了输出或者调整了路径。可以在FreshRSS后台“订阅管理”里更新该源,看返回的状态码是200还是404。

如果源输出正常但还是抓不到,可能是源服务器的TLS版本太老,而FreshRSS容器内的PHP默认要求较高的加密协议。这种情况很少见,但出现过。另一个常见原因是源站有反爬策略,对非浏览器UA请求直接拒绝。FreshRSS允许为每个订阅源自定义User-Agent和HTTP头,可以在源设置里伪装成浏览器的UA试试,比如:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36

如果还是不行,就考虑用全文抓取或者RSSHub这类中间服务来生成可用的RSS源。

5.4 迁移服务器后登录态失效

FreshRSS的会话数据默认也存放在data目录里,迁移时如果不完整复制整个data目录,登录状态、API Token都会丢失。所以备份必须包含整个data目录,别只想着数据库文件。迁移后如果登录提示“会话无效”,先确认备份完整,必要时在后台重新生成用户API Token,手机会自动重新要求授权。

6. 写在最后的一点经验

FreshRSS我用了快两年,最直观的感受是,阅读习惯真的会被重建。刚开始从推荐流切回RSS时,总担心错过什么。后来发现,真正重要的信息基本不会因为你晚看到24小时就失去价值,反而是被算法推着走的日子,每天都处在一种“不看就落后”的错觉里。

搭建FreshRSS本身不是难事,难的是你愿意为“自己掌控信息输入”这件事花一点时间。现在部署方案已经做到了十分钟级别,移动端有成熟的客户端,数据完全握在自己手里,没有广告,没有隐私采集,没有任何人猜你想看什么。这种感觉,用过的人都会懂。如果你手头正好有一台闲置的服务器,或者正准备尝试自托管,FreshRSS是一个绝佳的入手项目——轻量、实用、一次搭好能用很多年。

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

E900V21E刷机全攻略:免拆与短接原理、实操与救砖指南

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

作者头像 李华
网站建设 2026/9/24 9:52:36

使用 Docker 在本地部署 Prisma 集群:`prisma local` 完整实战指南

后端数据库GraphQL 【免费下载链接】prisma1 💾 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL & MongoDB) [deprecated] 项目地址: https://gitcode.com/gh_mirrors/pr/prisma1 点击查看 免费下载 本指南基于 Prisma 1.x&a…

作者头像 李华
网站建设 2026/9/24 9:49:40

创维E900V21D机顶盒线刷救砖全攻略:从短接到固件选择一次搞定

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

作者头像 李华
网站建设 2026/9/24 9:49:18

ESP32-S3驱动JW01 CO2传感器:UART通讯与供电避坑实践

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

作者头像 李华
网站建设 2026/9/24 9:45:42

恶意代码可视化检测实战:从字节流到CNN图像分类

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

作者头像 李华