WeRSS(we-mp-rss)微信公众号 RSS 订阅助手部署与配置指南:Docker 一键启动、源码安装、过滤规则与全量环境变量详解
WeRSS(we-mp-rss)微信公众号 RSS 订阅助手部署与配置指南:Docker 一键启动、源码安装、过滤规则与全量环境变量详解
本篇技术指南以仓库根目录的 ReadMe.md 为主干,系统讲解 We-MP-RSS(WeRSS,微信公众号 RSS 订阅助手)的完整上手路径:从 Docker 秒级部署、一键升级、镜像选择,到本地前后端开发环境的搭建,再深入到 HTML 内容过滤规则的多维度配置与底层实现,最后给出全部 45 项环境变量的功能对照说明。读完本文,你可以独立完成该项目的部署、运行、二次开发与生产环境参数调优,并准确理解过滤规则引擎与配置加载机制的工作原理。
项目简介与核心特性
WeRSS 是一个面向微信公众号(WeChat Official Account)内容的订阅与管理工具,核心能力是把微信公众号文章转化为标准的 RSS 订阅源,让读者可以脱离微信 App、用任意 RSS 客户端继续追踪公众号更新。它在仓库中的项目名称为 we-mp-rss,前后端分离,遵循 MIT 开源协议。
从 ReadMe.md 的特性清单与 web.py 的路由组织可以看出,项目能力覆盖完整链路:
- 内容采集与解析:支持多种采集方式,包括
web、api、app、free_publish、playwright、weread、weread_mp、auto等模式(见 config.example.yaml 中gather.model的注释),其中weread_mp模式借助微信读书 Web 接口采集公众号文章,对应专项文档 docs/weread-mp.md。 - RSS 生成:支持自定义标题、描述、封面、全文/摘要、封面图开关、CDATA、分页大小,并可设置 RSS 域名与本地/外部链接切换。
- Web 管理界面:Vue 3 + Vite 构建的响应式前端,提供登录、订阅管理、文章浏览、配置管理、标签、级联状态、微信读书管理等多个管理页面(见 web_ui/src/views 目录)。
- 定时自动更新:默认开启
server.enable_job定时任务,由jobs包驱动文章抓取与通知。 - 多数据库支持:默认 SQLite(
sqlite:///./data/db.db),可选 MySQL、PostgreSQL(连接示例见 config.example.yaml)。 - 授权过期提醒与自定义通知:支持钉钉、微信、飞书、自定义 Webhook 四类通知渠道(对应 core/notice 目录的
dingtalk.py、wechat.py、feishu.py、custom.py、bark.py)。 - 导出能力:支持 Markdown、DOCX、PDF、JSON 格式导出(对应 apis/export.py 与 tools/mdtools)。
- API 与 WebHook:完整 REST API 与消息任务 WebHook 调用,支持自定义 Headers 与 Cookies 认证。
- HTML 内容过滤规则:全局规则 + 公众号专属规则,可批量清理文章中的广告、推荐链接等杂质(下文专章详解)。
- 级联系统(Cascade System):父子节点架构、智能任务分配,用于扩展采集能力,相关文档见 docs/CASCADE_GUIDE.md。
- 环境异常统计:自动跟踪访问微信文章时的环境异常并统计,对应 web_ui/src/views/EnvExceptionStats.vue。
- 配置缓存:支持 Redis、Memcached、内存缓存,提升配置读取性能。
系统架构概览
项目采用前后端分离架构,这一结论既来自 ReadMe.md 的 System Architecture 章节,也可以从源码得到印证:
- 后端:Python + FastAPI,Web 服务入口为 web.py,路由按
apis/下的业务模块分组注册,API 前缀由 core/config.py 中的API_BASE定义,自动生成 Swagger 文档(/api/docs)与 ReDoc 文档(/api/redoc)。 - 前端:Vue 3 + Vite,源码位于 web_ui,构建产物输出到
static/,由 FastAPI 静态挂载与 SPA 回退路由(web.py 中的serve_vue_app)托管。 - 数据库:SQLite(默认)/ MySQL,由 SQLAlchemy 驱动,模型定义集中在 core/models。
启动流程可参考 main.py:先初始化配置与可选的内置 Redis 服务(tools/redis_server.py),再按需启动认证服务、级联同步服务(子节点模式)、定时任务(cfg.args.job == "True" 且 server.enable_job)、文章内容自动补抓任务与统计刷新任务,最后以 uvicorn 运行 web:app,监听 0.0.0.0:8001。
Docker 快速部署(Quick Start)
ReadMe.md 提供了一条可直接执行的 Docker 命令,这是上手最快的方式:
docker run -d --name we-mp-rss -p 8001:8001 -v ./data:/app/data ghcr.io/rachelos/we-mp-rss:latest
启动后访问 http://<your-ip>:8001/ 即可进入 Web 界面完成初始化。
命令参数说明:
| 参数 | 含义 |
|---|---|
-d |
后台运行容器 |
--name we-mp-rss |
容器命名,便于后续 stop/rm 管理 |
-p 8001:8001 |
将容器 8001 端口映射到宿主机 |
-v ./data:/app/data |
将数据目录挂载到宿主机,持久化数据库、缓存与运行数据 |
生产环境建议在宿主机上为
./data指定确定路径,并配合环境变量注入数据库、密钥等敏感配置(参见下文环境变量章节)。官方镜像的构建方式可参考仓库根目录的 Dockerfile:镜像基于ghcr.io/rachelos/base-full:latest,安装 Python 依赖与 Playwright 浏览器,默认浏览器类型为webkit,并通过 start.sh 作为容器启动入口。
快速升级(Quick Upgrade)
当有新版本发布时,ReadMe.md 给出的升级流程是标准的“先删后建”:
docker stop we-mp-rss
docker rm we-mp-rss
docker pull ghcr.io/rachelos/we-mp-rss:latest
# If you added other parameters, please modify accordingly
docker run -d --name we-mp-rss -p 8001:8001 -v ./data:/app/data ghcr.io/rachelos/we-mp-rss:latest
由于数据卷 ./data:/app/data 与容器生命周期解耦,升级重建容器不会丢失已订阅的公众号与文章数据。若你之前的 docker run 额外追加过环境变量或端口映射参数,重建时需要按注释提示补回这些参数。
镜像选择:官方镜像与国内加速镜像
ReadMe.md 提供了两个镜像仓库地址:
# 官方镜像
docker run -d --name we-mp-rss -p 8001:8001 -v ./data:/app/data rachelos/we-mp-rss:latest
# 国内访问更快的代理镜像
docker run -d --name we-mp-rss -p 8001:8001 -v ./data:/app/data docker.1ms.run/rachelos/we-mp-rss:latest
rachelos/we-mp-rss:latest为官方 Docker Hub 镜像;docker.1ms.run/rachelos/we-mp-rss:latest为面向中国大陆网络的代理镜像,拉取速度更快。
仓库内 compose/docker-compose.yaml 还提供了一套完整的 compose 编排方案,除 we-mp-rss 主服务外,同时拉起 MySQL 8.3、Redis 7 与 sing-box 代理容器,适合需要 MySQL + Redis + 代理出口的生产场景,可直接在其基础上按需修改。
源码开发环境搭建
环境要求
依据 ReadMe.md,本地开发需要:
- Python >= 3.13.1
- Node >= 20.18.3
Python 依赖清单见仓库根目录的 requirements.txt,其中关键依赖包括 FastAPI 0.115、SQLAlchemy 2.0、APScheduler 3.11、Playwright 1.55、Selenium 4.27、BeautifulSoup4、lxml、redis-py 等;前端依赖见 web_ui/package.json。
后端服务
- 克隆项目并进入目录:
git clone https://github.com/rachelos/we-mp-rss.git
cd we-mp-rss
- 安装 Python 依赖:
pip install -r requirements.txt
- 生成并修改配置文件:
cp config.example.yaml config.yaml
Windows 下等价命令为 copy config.example.yaml config.yaml。默认配置即可用 SQLite 启动;若改用 MySQL,需把 db 配置为类似 mysql+pymysql://<username>:<password>@<host>/we-rss?charset=utf8mb4 的连接串。
- 启动服务(带初始化与定时任务):
python main.py -job True -init True
命令行参数在 core/config.py 中解析:-config 指定配置文件(默认 config.yaml),-job 控制是否启动定时任务,-init 控制是否初始化数据库与初始用户。启动后 API 服务默认监听 0.0.0.0:8001,Swagger 接口文档地址为 /api/docs。
前端开发
- 安装前端依赖:
cd we-mp-rss/web_ui
yarn install
- 启动前端开发服务(Vite 热更新):
yarn dev
- 访问前端页面:
http://localhost:3000
生产部署时由后端 FastAPI 直接托管 static/ 目录下构建产物(见 web.py 的 serve_vue_app SPA 回退路由),开发时则通过 Vite 独立端口联调。
HTML 内容过滤规则(Filter Rules)实战
采集到的公众号文章 HTML 中常混有广告、推荐位、脚注等冗余元素。ReadMe.md 专门用一章介绍了 WeRSS 的自定义 HTML 内容过滤规则,本节完整继承并进一步深入底层实现。
规则能力总览
- 全局规则:不绑定具体公众号,对所有账号生效。
- 公众号专属规则:可为特定公众号单独配置规则,
mp_id以 JSON 数组字符串存储,支持一规则多账号。 - 优先级控制:每条规则可设置 0–100 的优先级,数值越大越先执行。
- 六类过滤手段:
- 按元素 ID 移除(如
ad-banner) - 按 CSS Class 移除(如
ad-container) - 按 CSS 选择器移除(如
div.ad-wrapper、.recommend-list > li) - 按属性过滤(如
data-type="ad",支持仅按属性名或“属性名 + 属性值”精确/模糊匹配) - 按正则表达式移除内容区域
- 移除常见 HTML 元素(script、style、注释等)
- 按元素 ID 移除(如
Web 管理界面操作流程
- 登录管理后台,进入“过滤规则”页面;
- 点击“添加过滤规则”;
- 填写规则配置:
- 选择公众号:可选,留空即为全局规则;
- 规则名称:规则描述性名称;
- 优先级:数值越大优先级越高(0–100);
- 过滤配置:
- 移除 ID 元素:每行一个 ID,如
ad-banner; - 移除 Class 元素:每行一个 class,如
ad-container; - CSS 选择器:如
div.ad-wrapper、.recommend-list > li; - 属性过滤:如
data-type="ad"; - 正则表达式:用于精确匹配并移除内容。
- 移除 ID 元素:每行一个 ID,如
REST API 端点
过滤规则的增删改查接口实现在 apis/filter_rule.py,路由前缀为 /filter-rules:
# 获取过滤规则列表
GET /api/filter-rules
# 创建过滤规则
POST /api/filter-rules
{
"mp_id": "[]", // 空数组即全局规则
"rule_name": "Global Ad Filter",
"remove_ids": ["ad-banner"],
"remove_classes": ["ad-container"],
"priority": 10
}
# 更新过滤规则
PUT /api/filter-rules/{rule_id}
# 删除过滤规则
DELETE /api/filter-rules/{rule_id}
结合 apis/filter_rule.py 的源码可以看到更多细节:
- 创建接口(
create_filter_rule)接受remove_selectors、remove_attributes、remove_regex、remove_normal_tag等扩展字段; - 列表接口(
get_filter_rules)支持mp_id、limit(1–100)、offset分页查询,并按优先级降序排列; - 内部辅助函数
get_filter_rules_for_mp(mp_id)与apply_filter_rules(html_content, mp_id)负责在采集链路中按公众号匹配(全局规则 + 该公众号专属规则)并串行应用规则,所有状态为启用(DATA_STATUS.ACTIVE)的规则按priority DESC排序后逐个执行; - 数据库模型定义于 core/models/filter_rule.py,
mp_id为 JSON 字符串(存储多个公众号 ID 数组),规则状态、优先级、创建/更新时间等字段一应俱全。
底层过滤引擎实现
过滤规则最终由 tools/htmltools.py 中的 HtmlTools.clean_html() 统一执行,其执行顺序为:
- 构建统一选择器列表:将
remove_ids、remove_classes、remove_selectors、remove_xpaths归一化为{selector, type}字典; - 调用
remove_html_elements()基于 BeautifulSoup 按类型查找元素:CSS 用soup.select(),ID 用find_all(id=...),Class 用find_all(class_=...),XPath 则借助 lxml 树操作,最后对匹配元素执行decompose()移除; - 调用
remove_elements_by_attributes()按属性过滤:只给属性名则移除所有含该属性的元素,属性名 + 值则支持模糊(soup.select('[attr*="value"]'))与精确(find_all(attrs=...))两种匹配,eq字段控制精确/模糊; - 调用
remove_html_region()以re.sub正则移除指定内容区域,默认启用re.DOTALL | re.IGNORECASE; - 若开启
remove_normal_tag,则执行remove_common_html_elements(),内置移除script、style、HTML 注释的默认正则模式; - 可选地执行
remove_empty_text_elements(),移除无有效文本的包裹元素但保留img、video、audio等媒体标签。
这意味着你在界面上配置的每一类过滤项,都有明确的底层解析与移除策略支撑,规则的“优先级”决定了同一样式被多条规则命中时的应用次序。
环境变量配置全表
WeRSS 采用“配置文件模板 + 环境变量覆盖”的配置机制:配置文件本身写成 ${VAR:-default} 占位符形式(例如 port: ${PORT:-8001}),core/config.py 的 replace_env_vars() 会在加载时用环境变量值替换占位符,未设置则回退到默认值,get() 方法支持 db、gather.content_mode 这种点号嵌套取值,并自动把 "true"/"false"、纯数字字符串转换成本地类型。以下为 ReadMe.md 给出的全部环境变量对照表:
| 环境变量 | 默认值 | 说明 |
|---|---|---|
APP_NAME |
we-mp-rss |
应用名称 |
SERVER_NAME |
we-mp-rss |
服务名称 |
WEB_NAME |
WeRSS微信公众号订阅助手 |
前端显示名称 |
SEND_CODE |
False |
授权过期通知是否附带授权二维码(默认仅文本通知) |
CODE_TITLE |
WeRSS授权二维码 |
二维码通知标题 |
ENABLE_JOB |
True |
是否启用定时任务 |
AUTO_RELOAD |
False |
代码变更时自动重启服务 |
THREADS |
2 |
最大线程数 |
DB |
sqlite:///data/db.db |
数据库连接字符串 |
DINGDING_WEBHOOK |
空 | 钉钉通知 Webhook 地址 |
WECHAT_WEBHOOK |
空 | 微信通知 Webhook 地址 |
FEISHU_WEBHOOK |
空 | 飞书通知 Webhook 地址 |
CUSTOM_WEBHOOK |
空 | 自定义通知 Webhook 地址 |
SECRET_KEY |
we-mp-rss |
密钥 |
USER_AGENT |
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36/WeRss |
请求 User-Agent |
SPAN_INTERVAL |
10 |
定时任务执行间隔(秒) |
WEBHOOK.CONTENT_FORMAT |
html |
文章内容发送格式(可选 text、markdown) |
PORT |
8001 |
API 服务端口 |
DEBUG |
False |
调试模式 |
MAX_PAGE |
5 |
最大抓取页数 |
RSS_BASE_URL |
空 | RSS 域名地址 |
RSS_LOCAL |
False |
是否使用本地 RSS 链接 |
RSS_TITLE |
空 | RSS 标题 |
RSS_DESCRIPTION |
空 | RSS 描述 |
RSS_COVER |
空 | RSS 封面 |
RSS_FULL_CONTEXT |
True |
是否显示全文 |
RSS_ADD_COVER |
True |
是否添加封面图 |
RSS_CDATA |
False |
是否启用 CDATA |
RSS_PAGE_SIZE |
30 |
RSS 分页大小 |
TOKEN_EXPIRE_MINUTES |
4320 |
登录会话有效时长(分钟,默认 3 天) |
CACHE.DIR |
./data/cache |
缓存目录 |
ARTICLE.TRUE_DELETE |
False |
是否真实删除文章(为 True 时删除数据库记录) |
GATHER.CONTENT |
True |
是否采集文章内容 |
GATHER.MODEL |
app |
采集模式 |
GATHER.CONTENT_AUTO_CHECK |
False |
是否自动检查未采集文章内容 |
GATHER.CONTENT_AUTO_INTERVAL |
59 |
自动检查未采集内容的时间间隔(分钟) |
GATHER.CONTENT_MODE |
web |
内容修正模式 |
SAFE_HIDE_CONFIG |
db,secret,token,notice.wechat,notice.feishu,notice.dingding |
需隐藏的配置信息 |
SAFE_LIC_KEY |
RACHELOS |
授权加密密钥 |
LOG_FILE |
空 | 日志文件路径(空则不写文件) |
LOG_LEVEL |
INFO |
日志级别 |
EXPORT_PDF |
False |
是否启用 PDF 导出功能 |
示例配置中的扩展项与默认值差异提示
实际运行时以 config.example.yaml 的占位符默认值为准,该文件在上述表格之外还支持大量细分配置,例如:
- 数据库连接:
db: ${DB:-sqlite:///./data/db.db},注释中给出 MySQL 与 PostgreSQL 的连接串格式,并提示生产环境务必通过环境变量DB注入、不要使用默认值; - Redis 连接与内置 Redis 服务端:
redis.url(redis://[:password@]host:port/db)、redis.server.*(监听地址/端口/最大内存/认证密码/持久化开关,由tools/redis_server.py启动); - 抓取链路调优:
GATHER.CONTENT_FETCH_TIMEOUT(单篇正文抓取超时秒数)、GATHER.CONTENT_FETCH_STALE_TIMEOUT(FETCHING 锁自动恢复时间)、GATHER.CONTENT_BATCH_SIZE(每轮补抓数量)、GATHER.CONTENT_MAX_FAILURES(单篇最大失败次数)、GATHER.CONTENT_FALLBACK(失败是否回退到另一采集模式); - 采集模式枚举:
GATHER.MODEL可选web | api | app | free_publish | playwright | weread | weread_mp | auto,weread_mp模式需要微信读书 Cookie 与x-wr-ticket凭据,详见 docs/weread-mp.md; - 浏览器类型:
BROWSER_TYPE默认firefox,允许firefox/edge/webkit; - 代理配置:
proxy.enabled、proxy.deno_url(Deno Deploy 代理)、proxy.http_url(HTTP/SOCKS5 代理); - 微信读书配置段
weread.*(Cookie、ticket、vid、列表页数、请求间隔、自动加书架)与安全配置段safe.*; - 导出细分:
EXPORT_PDF_DIR、EXPORT_MARKDOWN、EXPORT_MARKDOWN_DIR; - 级联系统:
CASCADE_ENABLED、CASCADE_NODE_TYPE、CASCADE_PARENT_API_URL、CASCADE_API_KEY/SECRET、CASCADE_SYNC_INTERVAL、CASCADE_HEARTBEAT_INTERVAL、CASCADE_TASK_POLL_INTERVAL。
需要留意的是,ReadMe 表格中的 THREADS(2)、GATHER.CONTENT(True)、GATHER.MODEL(app)、GATHER.CONTENT_AUTO_CHECK(False)等默认值与示例配置文件的占位符默认值(分别为 1、False、web、True)存在差异,实际生效值以 config.example.yaml 复制生成的 config.yaml 为准,可自行按需调整。
安全使用建议
SECRET_KEY、DB、Redis 密码等敏感项在 config.example.yaml 中均有“生产环境请通过环境变量设置强随机值”的注释,部署时应通过环境变量注入,避免使用默认值;- 配置文件中
db、secret、token、各通知 Webhook 等字段默认被SAFE_HIDE_CONFIG隐藏,防止在管理界面中泄露; SAFE_LIC_KEY为授权加密密钥,修改后需要与应用侧保持一致。
多主题与前端体验
ReadMe.md 提到前端内置 13 套主题(默认紫、蓝、绿、橙、玫瑰、青、粉、靛蓝、紫罗兰、咖啡、藏青、深色模式、棕黄),并支持响应式分页(PC 端点击翻页、移动端“加载更多”)。相关实现可参考 web_ui/src/views/ArticleListDesktop.vue 与 web_ui/src/views/ArticleListMobile.vue,分别对应桌面端与移动端的列表渲染策略。主界面截图如下:
延伸阅读与部署建议
- 微信读书采集模式(
weread_mp)的完整配置说明见 docs/weread-mp.md; - 级联系统(父-子节点任务分发)从概念到排障的文档链包括 docs/CASCADE_README.md、docs/CASCADE_GUIDE.md、docs/CASCADE_IMPLEMENTATION.md 与 docs/TROUBLESHOOTING_CASCADE.md;
- 环境变量异常统计能力见 web_ui/src/views/EnvExceptionStats.vue 与后端 apis/env_exception.py;
- 完整特性与中文介绍可对照 README.zh-CN.md。
部署层面给出的推荐路径是:个人尝鲜直接用 ReadMe.md 的单容器 Docker 命令;需要 MySQL + Redis + 代理的生产环境可套用 compose/docker-compose.yaml 的 compose 编排;需要二次开发则按上文“源码开发环境搭建”同时启动后端(python main.py -job True -init True)与前端(yarn dev)。无论哪种方式,请务必先梳理清楚数据库连接、密钥、采集模式、RSS 输出格式这几组关键环境变量,再对公众号执行批量订阅,即可获得稳定、干净的微信公众号 RSS 阅读体验。


