1. 适用版本与准备工作
本文适用于 wcplusPro V10 的远程数据服务。通过 API Token 调用需要 Max 授权;Pro 可通过登录后的远程网页浏览和下载,但不支持专用数据 API。使用浏览器会话调用专用数据接口,同样要求 Max。
这些接口只读取已经保存的数据,不会自动打开微信、重新采集文章或临时转换 Markdown 正文。本文只介绍读取与导出,不包含创建或删除采集任务的操作。
开始前:
- 在桌面应用中完成数据采集,确认需要的正文已保存。
- 打开“设置 → 远程服务”,配置访问密码、监听范围和端口,保存并启动。
- 从应用设置获取 API Token。它与网页登录密码是不同的凭据。
- 保持采集电脑上的应用运行,确认调用端能够访问该服务。
默认端口为 5001,以应用中实际配置为准。同机调用可使用 http://127.0.0.1:5001;其他设备使用采集电脑在远程服务页面显示的地址。
旧文档中的 /api/gzh/list、/api/report/gzh_articles、/api/article/export_text 等路径不适用于本文。V10 使用 /api/v1/ 前缀,不能继续采用“无需 Token”的调用方式。
2. 鉴权与连通性检查
每个脚本请求携带以下请求头:
Authorization: Bearer YOUR_API_TOKEN
在终端设置自己的服务地址和 Token 后,先请求能力信息:
export WCPLUS_BASE_URL='http://127.0.0.1:5001'
export WCPLUS_API_TOKEN='替换为应用中显示的 API Token'
curl --fail-with-body \
-H "Authorization: Bearer $WCPLUS_API_TOKEN" \
"$WCPLUS_BASE_URL/api/v1/info"
返回字段包括 apiVersion、serverTime、contentFormats、maxPageSize、maxContentBatch、maxMarkdownBytes、maxContentBatchBytes 和 openapi。serverTime 为 Unix 秒,可用作增量同步窗口的上界。
机器可读的 OpenAPI 规范位于:
curl --fail-with-body \
-H "Authorization: Bearer $WCPLUS_API_TOKEN" \
"$WCPLUS_BASE_URL/api/v1/openapi.json"
修改远程访问密码并重启服务会更新 API Token,调用端也需要更新凭据。服务未启用 CORS;跨站网页不能把它当成任意可跨域调用的公共接口。建议由自己的脚本或服务端发起请求,不要将 Token 写入公开网页或代码仓库。
3. 数据接口总览
以下接口均使用 GET。路径中的 biz 和 id 应使用接口返回的原始标识,并进行 URL 编码,不要用公众号昵称或文章标题代替。
| 路径 | 用途 | 响应 |
|---|---|---|
/api/v1/accounts | 已有文章的公众号清单 | 分页 JSON |
/api/v1/accounts/{biz} | 单个公众号元数据 | GZH JSON 对象 |
/api/v1/accounts/{biz}/articles | 指定公众号文章清单 | 分页 JSON |
/api/v1/articles | 跨公众号文章清单,可按 biz 筛选 | 分页 JSON |
/api/v1/articles/{id} | 单篇文章元数据及阅读指标 | Article JSON 对象 |
/api/v1/articles/{id}/content | 单篇元数据及 Markdown 状态 | article、content 对象 |
/api/v1/articles/{id}/markdown | 单篇 Markdown 原文 | text/markdown |
/api/v1/accounts/{biz}/contents | 按公众号批量读取正文 | 正文分页 JSON |
/api/v1/articles/contents | 跨公众号批量读取正文 | 正文分页 JSON |
/api/v1/accounts/export?format=json | 下载公众号元数据,支持 json、csv | 文件流 |
/api/v1/accounts/{biz}/export?format=csv | 下载文章元数据,支持 json、csv | 文件流 |
/api/v1/accounts/{biz}/export?format=markdown | 下载缓存正文 ZIP | ZIP 文件流 |
元数据保留原始 JSON 字段。文章常用字段有 id、biz、title、author、pDate、readNum、likeNum、oldLikeNum、shareNum、commentNum、rewardNum、readingDataStatus、createdAt、updatedAt 等;完整字段以实际响应和 OpenAPI 为准。
这些下载接口将文件内容返回给调用端,不是在采集电脑上生成一个供脚本打开的文件路径。桌面应用中的 XLSX 导出与这里的 JSON、CSV、Markdown ZIP 下载是不同入口。
4. 分页、筛选与排序
公众号清单
/api/v1/accounts 支持 page、pageSize、q 和 sort。页码从 1 开始,默认每页 50 条,最多 200 条。q 搜索公众号名称或 Biz。
可排序字段:biz,nickname,localArticleNum,totalArticleNum,readingDataArticleNum,createdAt,updatedAt。
curl --fail-with-body -G \
-H "Authorization: Bearer $WCPLUS_API_TOKEN" \
--data-urlencode 'page=1' --data-urlencode 'pageSize=50' \
--data-urlencode 'sort=-updatedAt,nickname' \
"$WCPLUS_BASE_URL/api/v1/accounts"
响应包含 items、total、page 和 pageSize。该清单只包含已有文章的公众号。
文章与批量正文
| 参数 | 说明 |
|---|---|
offset | 从 0 开始的偏移,作用于筛选、排序后的结果 |
num | 元数据默认 50,范围 1–200;批量正文默认 20,范围 1–20 |
page,pageSize | 兼容页码分页,不能与 offset/num 混用;正文每批仍最多 20 篇 |
q | 文章标题或作者包含搜索,不是正文全文检索 |
sort | 逗号分隔多个字段,前缀负号表示降序,例如 -readNum,-pDate |
startDate,endDate | 发布日期,YYYY-MM-DD,按北京时间解释,包含结束日 |
readingStatus | pending、succeeded、failed,仅代表阅读指标状态 |
updatedSince | 文章更新时间起点,Unix 秒,包含边界 |
updatedBefore | 更新时间终点,Unix 秒,不包含边界;需大于起点 |
afterId | ID 升序游标;使用 sort=id,不能与 offset 大于 0、page 大于 1 或其他排序混用 |
biz | 跨公众号接口的可选公众号筛选 |
view=table | 元数据的精简表格字段模式;系统集成通常省略,正文批量接口不支持 |
文章排序字段包括 id,title,author,pDate,idx,mov,readNum,likeNum,oldLikeNum,shareNum,commentNum,rewardNum,followerNum,readingDataStatus,createdAt,updatedAt,digest,original,localArticle,postLocation。默认排序为 -pDate,mov,ID 的字典顺序与发布时间无关。
文章与正文分页响应包含 items,total,page,pageSize,offset,num,hasMore,nextOffset,nextAfterId。其中:
num是实际返回条数,不一定等于请求值。nextOffset为下一批偏移,没有后续时为null。nextAfterId仅在 ID 升序且还有下一批时提供。- 使用
afterId时,total是游标之后的匹配数量,不是全库数量。
正文每篇最多 8 MiB,每批 Markdown 原文合计最多 16 MiB。达到字节上限时,一批可能少于请求数量,必须按返回的续读字段推进,不能自行加上请求的 num。
5. 正文状态与返回结构
/content 和批量 /contents 返回的每一项包含文章元数据与正文状态。以下为字段示意,文章字段已省略:
{
"article": {"id": "ARTICLE_ID", "biz": "BIZ", "title": "示例文章"},
"content": {
"format": "markdown",
"status": "ready",
"body": "# Example",
"bytes": 9,
"modifiedAt": 1791676800
}
}
| content.status | 含义 | 是否有 body |
|---|---|---|
| ready | 缓存正文可用 | 有 |
| stale | 缓存正文可读,但源缓存更新较新 | 有,但可能过时 |
| missing | 未生成或已删除正文 | 无 |
| empty | 正文为空 | 无 |
| unavailable | 无法读取正文 | 无 |
| ambiguous | 账号改名后存在多个候选,无法唯一确定 | 无 |
| too_large | 超出单篇限制 | 无 |
bytes 是返回正文的 UTF-8 字节数,modifiedAt 是缓存文件的 Unix 秒。readingStatus 与 content.status 相互独立,阅读指标成功不代表正文已准备好。
只要文章记录存在,/content 可以用 HTTP 200 返回元数据和缺失状态;某篇正文缺失不会阻止同批其他文章返回。API 不会因此重新采集或转换正文,也不返回本机文件路径。
纯 /markdown 接口在正文可用时直接返回文本,并通过 X-Content-Status 标明 ready 或 stale;正文不可用时返回 404,单篇超限返回 413。需要最新正文的系统应明确决定是否接受 stale。
6. Python:读取单篇与下载文件
安装依赖:
python -m pip install requests
下面的片段共用这一段初始化代码。服务地址和 Token 从前述环境变量读取,真实凭据无需写进脚本:
import os
from pathlib import Path
from urllib.parse import quote
import requests
BASE_URL = os.environ["WCPLUS_BASE_URL"].rstrip("/")
session = requests.Session()
session.headers["Authorization"] = "Bearer " + os.environ["WCPLUS_API_TOKEN"]
def read_json(path, params=None):
response = session.get(BASE_URL + path, params=params, timeout=(10, 120))
response.raise_for_status()
return response.json()
先获取文章列表,再读取第一篇文章的正文状态:
page = read_json("/api/v1/articles", {"offset": 0, "num": 1})
if page["items"]:
article_id = quote(page["items"][0]["id"], safe="")
result = read_json(f"/api/v1/articles/{article_id}/content")
content = result["content"]
if content["status"] == "ready":
Path("article.md").write_text(content["body"], encoding="utf-8")
else:
print("正文尚未就绪:", content["status"])
下载指定公众号全部匹配文章的 CSV。将 BIZ 替换为公众号清单返回的 biz:
biz = quote("BIZ", safe="")
with session.get(
f"{BASE_URL}/api/v1/accounts/{biz}/export",
params={"format": "csv", "sort": "-pDate,mov"},
stream=True,
timeout=(10, 120),
) as response:
response.raise_for_status()
with Path("articles.csv").open("wb") as output:
for chunk in response.iter_content(chunk_size=64 * 1024):
output.write(chunk)
将 format 改为 markdown、输出文件名改为 articles.zip,即可下载缓存正文 ZIP。ZIP 中的 manifest.json 会标记缺失正文;应检查清单,而不是仅凭下载成功判断每篇正文都齐全。
导出支持对应的搜索、日期、阅读状态和排序条件,包含所有匹配记录,不限于网页当前页。
7. Python:按稳定游标批量读取正文
下面的代码追加在初始化片段后运行,将可用正文按文章 ID 保存为文件,并记录每篇状态。文件名使用 ID 的哈希,避免标题重复或 ID 中的路径字符影响保存。
import hashlib
import json
output_dir = Path("wcplus-export")
output_dir.mkdir(exist_ok=True)
upper = read_json("/api/v1/info")["serverTime"]
params = {"sort": "id", "num": 10, "updatedBefore": upper}
with (output_dir / "manifest.jsonl").open("w", encoding="utf-8") as manifest:
while True:
page = read_json("/api/v1/articles/contents", params)
for item in page["items"]:
article = item["article"]
content = item["content"]
record = {"id": article["id"], "status": content["status"]}
# 示例只保存 ready;需要接受旧缓存时可另行处理 stale。
if content["status"] == "ready":
filename = hashlib.sha256(article["id"].encode()).hexdigest() + ".md"
(output_dir / filename).write_text(content["body"], encoding="utf-8")
record["file"] = filename
manifest.write(json.dumps(record, ensure_ascii=False) + "\n")
if not page["hasMore"]:
break
cursor = page.get("nextAfterId")
if not cursor or cursor == params.get("afterId"):
raise RuntimeError("接口未返回有效的下一批游标,停止本轮读取")
params["afterId"] = cursor
这个示例会在当前目录写入或覆盖同名导出文件与清单。需要保留历次结果时,请为每轮使用独立的输出目录。
ID 游标有助于避免 offset 位置移动造成的遗漏,但它不是数据库快照。同步期间新增较小 ID、修改或删除记录,仍可能改变遍历结果。
8. 增量同步与模型接入
持续同步时,为每一轮固定更新时间窗口 [updatedSince, updatedBefore):
- 从
/info获取本轮serverTime,作为固定上界。 - 起点使用上一轮成功完成时保存的上界,可适当重叠秒级边界。
- 本轮保持同一组窗口、筛选条件与
sort=id,通过nextAfterId续读。 - 按文章 ID 更新或插入目标系统的数据;重叠结果也按 ID 去重。
- 只有整轮完成后,才保存新的同步进度。失败时不要直接跳到下一窗口。
正文缓存状态与文章更新时间并非同一个概念。对 missing、stale 等待处理的文章,应保留 ID 并安排重读,不能仅依赖文章更新时间窗口来判断正文是否已经补齐。
当前没有删除事件流;需要同步删除时,定期校对完整 ID 清单。
接入 AI、知识库或自建 MCP 工具时,建议先检索元数据,再按需读取每批 1–10 篇正文。/api/v1/openapi.json 可用于生成客户端或封装工具;wcplusPro 提供的是 HTTP API,并不因此等同于内置 MCP 协议服务。
9. 常见错误
错误通常返回包含 error 的 JSON;授权错误可能附带所需级别等字段。
| HTTP 状态 | 排查方向 |
|---|---|
| 400 | 参数无效、分页方式混用、正文 num 超限、日期或排序不合法 |
| 401 | Token 缺失或失效,检查是否重置过密码 |
| 403 | 当前授权不支持该 API,或跨域写请求被拒绝 |
| 404 | 文章不存在,或纯 Markdown 接口没有可用正文 |
| 413 | 纯 Markdown 正文超过单篇大小限制 |
| 429 | 登录请求过于频繁 |
| 500 | 服务端读取失败,检查应用日志 |
| 503 | 内容服务不可用 |
空列表会返回 HTTP 200、items: [] 和 hasMore: false,不需要将其视为错误。网络超时则应检查采集电脑、远程服务、地址端口和网络可达性。
需要协助时,请提供接口路径、脱敏后的参数、HTTP 状态和错误信息,前往客服页面联系支持。不要将真实 API Token 放入截图或公开日志。