乐于分享
好东西不私藏

neurapress-cms 技术调研文档

neurapress-cms 技术调研文档

neurapress-cms 是一个自动化微信公众号文章发布管线。

核心流程:

数据源采集 (RSS/API) → AI 内容生成 → Markdown → HTML (适配微信) → 微信草稿箱

关键约束:

  • 微信文章仅支持内联 CSS,不支持外部样式表
  • 图片必须通过微信 API 上传至微信 CDN,外链图片会被过滤
  • 未认证个人订阅号无法调用发布 API,只能创建草稿,最终发布需在微信后台手动操作

2. 微信公众号 API 调研

2.1 认证机制 (access_token)

获取 access_token:

GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数
必填
说明
grant_type
固定值 client_credential
appid
公众号的唯一凭证
secret
公众号的 appsecret

成功响应:

{"access_token":"ACCESS_TOKEN","expires_in":7200}

错误响应:

{"errcode":40013,"errmsg":"invalid appid"}

关键注意事项:

  • access_token 有效期 2 小时(7200 秒),必须缓存,重复请求会使旧 token 失效
  • 存储空间至少预留 512 字符
  • 必须在「微信公众平台 > 开发 > 基本配置 > IP 白名单」中配置服务器 IP,否则返回错误码 40164
  • 刷新 token 时,新旧 token 在 5 分钟内同时有效
  • 最佳实践:使用中央服务统一获取和刷新 access_token,其他服务从该中央服务获取

2.2 草稿箱 API

创建草稿:

POST https://api.weixin.qq.com/cgi-bin/draft/add?access_token=ACCESS_TOKEN

官方文档:

  • 订阅号:https://developers.weixin.qq.com/doc/subscription/api/draftbox/draftmanage/api_draft_add.html
  • 服务号:https://developers.weixin.qq.com/doc/service/api/draftbox/draftmanage/api_draft_add.html

请求体(JSON)— articles 数组,每篇文章包含:

参数
说明
title
文章标题
author
作者
digest
文章摘要
content
文章正文(HTML)
content_source_url
原文链接
thumb_media_id
封面图 media_id(必填
need_open_comment
是否开启评论(0=否, 1=是)
only_fans_can_comment
仅粉丝可评论(0=所有人, 1=仅粉丝)
pic_crop_235_1
封面裁剪坐标(2.35:1 比例)
pic_crop_1_1
封面裁剪坐标(1:1 比例)

限制:

  • 每篇文章最多 20 张图片
  • 第一张图片为封面
  • 裁剪坐标使用 (0,0) 左上角到 (1,1) 右下角的坐标系
  • draft/add
     和 media/uploadimg 即使未认证的个人订阅号也可调用

2.3 发布 API

POST https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token=ACCESS_TOKEN

重要限制(2025 年中): 微信已撤销未认证个人账号的发布 API 权限。可以通过 API 创建草稿,但最终「发布」步骤需要在微信后台手动操作。个人账号暂无解决方案。

2.4 素材上传 API

API 1:上传文章内容图片 (media/uploadimg)

POST https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
  • 用于文章 content 字段中的内联图片
  • 返回 URL(不是 media_id)
  • 不占用素材库 100,000 条限额
  • 仅支持 jpg/png 格式,最大 1MB
  • 使用 POST form,字段名 media
curl -F media=@test.jpg "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN"

响应:

{"url":"http://mmbiz.qpic.cn/mmbiz/gLO17UPS6FS2xsypf378iaNhWacZ1G1UplZYWEYfwvuU6Ont96b1roYsCNFwaRrSaKTPCUdBK9DgEHicsKwWCBRQ/0"}

API 2:上传永久素材 (add_material)

POST https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE
  • 支持类型:image (10M), voice (2M), video (10M), thumb (64KB)
  • 返回 media_id — 用作封面图的 thumb_media_id
  • 永久素材图片 URL 仅在腾讯域名内可用(外部访问被屏蔽)
  • 素材库限额:图片/文章最多 100,000 条;其他类型最多 1,000 条

发布文章的完整工作流

  1. 通过 media/uploadimg 上传文章内联图片,获取 URL
  2. 通过 material/add_material (type=image) 上传封面图,获取 media_id 作为 thumb_media_id
  3. 通过 draft/add 创建草稿,包含 HTML 内容和 thumb_media_id
  4. 通过 freepublish/submit 发布(仅已认证账号)

2.5 图片托管规则

  • 外部图片链接会被过滤 — 不能使用外部 CDN 或图床
  • 必须通过微信 API 上传media/uploadimg
     或 material/add_material
  • 微信图片有防盗链保护 — 不能从外部网站引用
  • 仅支持 HTTPS 协议图片
  • 粘贴到微信编辑器的图片会自动上传到微信服务器
  • 静态图片宽度建议 1080px(PNG-24 格式减少压缩损失)
  • 宽度超过 1080px 会被压缩
  • 单张图片像素面积(宽 × 高)不能超过 6,000,000
  • GIF:最多 300 帧,建议 12-20fps,640px 宽度,超过 1000px 宽度压缩显著增大

2.6 频率限制

  • 每个公众号每个 API 有默认频率限制
  • 超限返回:{"errcode": 45009, "errmsg": "api freq out of limit"}
  • 可在「微信公众平台 > 开发中心 > 接口权限」查看当日调用限额和实时使用量
  • 已认证账号可重置配额
  • 清除配额 API:POST https://api.weixin.qq.com/cgi-bin/clear_quota?access_token=ACCESS_TOKEN
  • 订阅号:每天最多群发 1 次,每次最多 8 篇文章
  • 服务号:每月最多群发 4 次,每次最多 8 篇文章
  • Token 刷新:最多 200 次/分钟(企业微信)
  • 核心问题:access_token 获取过于频繁会触发限流,必须缓存

2.7 多账号管理

  • 第三方平台模式:通过 authorizer_access_token
     管理多个公众号
  • 独立客户端模式:每个账号有独立的 appid/appsecret,创建独立的客户端实例

2.8 wechatpy Python SDK

  • PyPIwechatpy
     v1.8.18(最新版)
  • GitHub
    https://github.com/wechatpy/wechatpy (4.2k stars, 2026年1月更新)
  • License: MIT
  • 安装
    pip install wechatpypip install 'wechatpy[cryptography]'# 推荐
  • 功能覆盖:公众号 API、企业微信 API、微信支付 API、第三方平台 API、小程序云 API
  • 依赖:python-dateutil>=2.5.2, cryptography>=3.1, requests-pkcs12>=1.7
  • 相关项目:wechatpy-asyncio(异步变体)、WeRoBot(4.7k stars)

3. 微信文章 HTML/CSS 限制

3.1 支持的 HTML 标签

文本与结构:

  • <p>
    <h1><h6><span><section><div>(可能被转换为 <p>
  • <strong>
    /<b><em>/<i><u><br><hr>
  • <article>
    <aside><header><footer><nav>

链接与媒体:

  • <img>
    (仅 HTTPS,仅网络图片;支持 jpg, png, gif, svg)
  • <a>
    (订阅号:仅内部链接;带微信支付的服务号:可外部链接)
  • 微信专属标签:<mpvoice>(语音消息)、<mpvideo>(视频)

列表:

  • <ul>
    <ol><li>(最多 2 层嵌套)

表格:

  • <table>
    <thead><tbody><tfoot><tr><td><th><caption><col><colgroup>
  • 支持 colspanrowspanwidthheight 属性

代码:

  • <pre>, <code>(基础支持,但有诸多渲染问题)

文本格式:

  • <del>
    <ins><mark><small><sub><sup><s>
  • <blockquote>
    <address><cite><abbr><q><ruby><rt>
  • <center>
    <font><fieldset><legend><label>
  • <dd>
    <dl><dt>

3.2 CSS 限制

仅支持内联样式:

  • 不支持 <style> 标签
  • 不支持 <link> 外部样式表
  • 不支持外部 CSS 文件
  • 所有样式必须通过元素的 style 属性设置
  • 类似邮件 HTML 的渲染方式

支持的 CSS 属性(内联):

  • 排版:font-sizefont-familyfont-weightcolorline-heightletter-spacingtext-aligntext-decoration
  • 盒模型:marginpaddingborderborder-radius
  • 布局:display(有限制), widthmax-widthheightoverflow
  • 背景:background-colorbackground-image(URL 值中的引号会被去除)
  • 视觉:box-shadowopacity
  • 变换:transform(现在可用,以前被去除)

被去除/禁止的 CSS 属性:

  • position(absolute/relative/fixed)— 上传后被完全移除
  • 所有 id 属性被去除(HTML 和 SVG 均如此)
  • <script>标签完全禁止
  • <iframe>不支持
  • 百分比单位可能失效(如 transform:translateY(-100%)),使用 pxvwvh 替代

其他约束:

  • <div>可能被转换为 <p> 存储
  • 微信会移除多余标签:<p><span>xxx</span></p> 变为 <p>xxx</p>
  • 未包裹的文本会自动添加 <p> 标签
  • 标签前的空格会被移除,使用 &nbsp; 进行缩进
  • 正文字号建议 15px
  • 标题通常使用 h2-h4
  • 支持 class 属性(但 id 不支持)
  • 宽度 360px 常用于保证跨设备一致显示

3.3 代码块问题与解决方案

问题:

  • 微信自带代码块功能简陋 — 不支持语法高亮
  • <style>
     标签和 CSS 定义会被过滤,保存后样式丢失
  • 空格/缩进被移除 — 必须使用 &nbsp;
  • 保存后换行可能丢失
  • 移动端(尤其 iOS)水平滚动可能失效
  • 原生不支持语法高亮

解决方案:

  • 使用 Markdown 转换工具(Md2All、Doocs-MD)输出内联样式代码
  • 使用 highlight.js 预渲染语法高亮
  • Chrome 扩展:crx_wx_code_highlight 用于微信平台
  • 使用 Carbon 将代码转换为图片

3.4 SVG 限制

  • SVG 内的 <style><script><a> 标签不允许
  • 所有 SVG ID 被去除
  • SVG 不能嵌套其他 SVG(图片嵌套现在有限支持:href 必须引用微信素材库)
  • iOS 特有问题:动画在重复点击时重新执行;<g> 标签中的内联样式在 iOS 上失效

4. 技术选型

4.1 推荐库及版本

版本
用途
选择理由
httpx
0.28.1
HTTP 客户端
同步+异步,requests 兼容 API,支持 HTTP/2
feedparser
6.0.12
RSS/Atom 解析
久经考验,支持 RSS 0.9x-2.0、Atom 0.3-1.0、CDF
fastfeedparser
latest
RSS 解析备选
比 feedparser 快 10-25 倍,Kagi 支持,兼容 API
beautifulsoup4
latest
HTML 解析/爬取
最流行,社区广泛
mistune
3.2.0
Markdown → HTML
比 Python-Markdown 快 3-4 倍,无依赖,CommonMark 兼容,支持自定义渲染器和插件
Jinja2
latest
HTML 模板
模板继承,自动转义,广泛使用
pydantic-settings
2.13.1
配置管理
类型安全,支持 .env/TOML/JSON/YAML,云密钥管理器集成
APScheduler
3.11.2
任务调度
Cron/间隔/一次性调度,同步+异步,成熟稳定
SQLAlchemy
2.0.x
ORM/数据库
健壮,异步支持(配合 asyncpg),Alembic 迁移,类型提示
asyncpg
latest
异步 PostgreSQL 驱动
高性能,纯 Python,SQLAlchemy 异步 PostgreSQL 所需
psycopg
3.x
PostgreSQL 驱动(备选)
psycopg2 的下一代,支持同步+异步,纯 Python 和 C 加速两种模式
wechatpy
1.8.18
微信 SDK
最流行的 Python 微信 SDK,MIT 协议,活跃维护
anthropic
0.84.0
Claude AI API
官方 SDK,同步+异步,流式传输
openai
latest
OpenAI API
官方 SDK

APScheduler 4.0(alpha)注意:重大重写有破坏性变更 — workers 合并到 schedulers,job executor 概念,仅异步数据存储。生产环境使用 3.11.2。

4.2 Markdown 库对比

特性
Mistune
Python-Markdown
Marko
速度
最快 (13.9ms)
中等 (48.4ms)
中等
CommonMark
部分
GFM 支持
通过插件
通过扩展
内置
依赖
自定义渲染器

推荐 mistune:速度优势明显,无依赖,插件系统灵活,可自定义渲染器输出微信兼容 HTML。


5. 项目结构

采用 src layout(PyPA 推荐):

api/├── pyproject.toml├── README.md├── src/│   └── neurapress_cms/│       ├── __init__.py│       ├── config.py            # pydantic-settings 配置│       ├── models/              # SQLAlchemy 模型│       │   ├── __init__.py│       │   ├── source.py│       │   ├── material.py│       │   ├── article.py│       │   ├── wechat_account.py│       │   └── publish_record.py│       ├── services/            # 业务逻辑│       │   ├── __init__.py│       │   ├── collector.py     # RSS/API 数据采集│       │   ├── ai_generator.py  # AI 内容生成│       │   ├── converter.py     # Markdown → WeChat HTML│       │   └── publisher.py     # 微信 API 交互│       ├── scheduler/           # APScheduler 任务│       │   ├── __init__.py│       │   └── jobs.py│       └── templates/           # Jinja2 HTML 模板│           └── wechat_article.html└── tests/    ├── test_collector.py    ├── test_converter.py    └── test_publisher.py

为什么选择 src layout:

  • 明确可导入代码的位置
  • 避免 flat layout 常见的导入问题
  • 任何可安装项目或含测试项目的现代标准

pyproject.toml 作为中央配置文件:

  • [build-system]
     — 声明构建后端
  • [project]
     — 基本元数据、依赖
  • [tool]
     — 工具配置(pytest, black, mypy 等)
  • 替代 setup.py, setup.cfg, requirements.txt

6. 数据库设计

6.1 异步 PostgreSQL 配置

from sqlalchemy.orm import DeclarativeBasefrom sqlalchemy.ext.asyncio import AsyncAttrs, async_sessionmaker, create_async_engineDATABASE_URL = "postgresql+asyncpg://user:password@localhost:5432/neurapress_cms"engine = create_async_engine(url=DATABASE_URL, pool_size=5, max_overflow=10)async_session_maker = async_sessionmaker(engine, expire_on_commit=False)classBase(AsyncAttrs, DeclarativeBase):    __abstract__ = True

最佳实践:

  • 每个任务一个 AsyncSession
  • 使用 lazy="raise" 防止隐式 I/O(懒加载)
  • 设置 expire_on_commit=False
  • 配置连接池:pool_size(默认连接数)和 max_overflow(溢出连接数)
  • 使用 select() 风格查询(2.0 模式)
  • 使用 Alembic 进行数据库迁移
  • 开发环境可通过 Docker 运行 PostgreSQL:docker run -d -p 5432:5432 -e POSTGRES_DB=neurapress_cms -e POSTGRES_PASSWORD=password postgres:16

6.2 核心模型

模型
说明
Source
数据源(RSS 订阅、API 等)
Material
采集的原始内容/素材
Article
生成的文章(Markdown + HTML)
WeChatAccount
微信公众号凭证(appid, appsecret, access_token 等)
PublishRecord
文章发布状态记录(关联 Article 和 WeChatAccount)

7. 开源参考项目

Doocs Markdown Editor(推荐)

  • GitHub
    https://github.com/doocs/md
  • 在线版
    https://md.openwrite.cn/
  • 功能:Markdown 转微信 HTML,自定义主题,多图床支持,AI 助手,Docker 部署,npm CLI(@doocs/md-cli

WenYan (wxmp)

  • 多平台适配器(微信、知乎、头条)
  • “WenYan MCP Server” 支持 AI 辅助直接发布到微信草稿箱,自动上传图片

wechat-format (lyricat)

  • GitHub
    https://github.com/lyricat/wechat-format
  • 已停止维护,作者推荐 Quaily Markdown Tools

vscode-markdown-to-wechat (xianmin)

  • GitHub
    https://github.com/xianmin/vscode-markdown-to-wechat
  • VSCode 扩展,使用 remark 库,主题系统,TypeScript

BND-1/wechat_article_skills

  • 综合工具包:Markdown 转 HTML、AI 写作助手、草稿发布工具

其他工具

  • Markdown-Weixin: https://md.qikqiak.com/
  • BTool: https://md.btool.cn/
  • Markdown Here 浏览器插件
  • 135 编辑器、96 编辑器、秀米

8. 关键风险与注意事项

  1. 个人订阅号发布限制:未认证个人账号无法调用发布 API(freepublish/submit),只能创建草稿,最终发布需手动操作
  2. access_token 管理:必须缓存,频繁获取会触发限流;需实现中央 token 管理服务
  3. IP 白名单:调用微信 API 前必须配置 IP 白名单,否则返回 40164 错误
  4. 图片上传必经微信 CDN:所有文章图片必须通过微信 API 上传,外链图片会被过滤
  5. 内联 CSS 限制position
     属性被完全移除,id 属性被去除,必须使用内联样式
  6. 代码块渲染:微信原生不支持语法高亮,需使用 highlight.js 预渲染或 Doocs-MD 等工具
  7. SVG 限制:SVG 内不允许 <style>
    <script><a>,所有 ID 被去除
  8. 群发限制:订阅号每天最多 1 次,每次最多 8 篇;服务号每月最多 4 次
  9. APScheduler 版本选择:4.0 为 alpha 版本有破坏性变更,生产环境使用 3.11.2
  10. 百分比 CSS 单位:可能在微信中失效,优先使用 px, vwvh
本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » neurapress-cms 技术调研文档

评论 抢沙发

1 + 4 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮