微信读书 API 文档
04 - 微信读书 API 文档研究笔记
日期:2026-08-14
用途:个人动态页"阅读动态"模块数据来源(取代原 GitHub 动态)
接入方式:微信读书 Agent Gateway(个人 API Key)
相关代码:usr/themes/classic-22/inc/weread-client.php(客户端)、usr/themes/classic-22/inc/weread-activity.php(聚合与渲染)
认证方式
Authorization: Bearer WEREAD_API_KEY
Content-Type: application/json- API Key 存放在
config.inc.php的WEREAD_API_KEY(已在.gitignore,不提交 Git) - 也可通过环境变量
WEREAD_API_KEY提供(wereadApiKey()优先取常量,其次取环境变量) - 注意:属于敏感凭证,维护文档中禁止出现真实值
Gateway 基本信息
| 项目 | 内容 |
|---|---|
| 端点 | POST https://i.weread.qq.com/api/agent/gateway |
| 请求版本 | skill_version: 1.0.4(可由 WEREAD_SKILL_VERSION 覆盖) |
| 认证 | Authorization: Bearer WEREAD_API_KEY |
| 超时 | 连接 4s / 总超时 8s,curl_multi 并行批量请求 |
请求体格式(重要)
参数拍平到顶层,不要把参数包在 params 对象里,否则返回 errcode=-2003:
{
"api_name": "/book/getprogress",
"bookId": "3300035133",
"skill_version": "1.0.4"
}通用回包约定
- 顶层
errcode为0表示成功;非 0 为失败(如-2003参数格式错误 / 缺少必填参数) - 回包出现
upgrade_info时表示需要升级 skill,本次请求失败 - 客户端
wereadDecodeGatewayResponse()已封装校验:HTTP 2xx +errcode==0且无upgrade_info才算成功 - 客户端
wereadBuildGatewayPayload()内部正是用array_merge($params, [...])把参数拍平到顶层
接口总览
| api_name | 说明 | 使用场景 |
|---|---|---|
/readdata/detail | 阅读数据统计(月度/年度等) | 第一波请求,params: {mode: monthly} |
/shelf/sync | 同步书架,返回书架上的书籍列表 | 第一波请求,无参数 |
/book/getprogress | 单本书阅读进度与时长的详细信息 | 第二波请求,params: {bookId},候选池每本一个 |
/readdata/detail(月度统计)
请求:{"api_name":"/readdata/detail","mode":"monthly","skill_version":"1.0.4"}
返回 data 关键字段:
| 字段 | 说明 |
|---|---|
totalReadTime | 本月总阅读时长,单位秒 |
readDays | 本月有效阅读天数 |
dayAverageReadTime | 按已过去自然日计算的日均时长,单位秒 |
readTimes | 每天阅读秒数映射({时间戳: 秒数}) |
readLongest[] | 本月阅读时长最长的若干本书(每项含完整 book 信息 + readTime + tags) |
readStat[] | "读过/读完/阅读/笔记"统计文案 |
preferBooks[] | 偏爱书籍(常读常新、近期偏爱、最沉浸等,按 type 区分) |
preferCategory[] | 偏好分类(按分类聚合阅读时长) |
注意:readLongest 只覆盖本月读得最多的少数几本,不等于"最近阅读"候选,不能作为展示过滤的唯一来源。
/shelf/sync(书架)
请求:{"api_name":"/shelf/sync","skill_version":"1.0.4"}
返回 data.books[] 单本书字段:
| 字段 | 说明 |
|---|---|
bookId | 书籍唯一 ID |
title | 书名 |
author | 作者 |
cover | 封面 URL(HTTPS) |
deepLink | 微信读书跳转链接(weread.qq.com 域) |
secret | 1 = 私密书籍 |
readUpdateTime | 最近阅读时间戳;<=0 表示未读 |
finishReading | 是否读完 |
updateTime / category | 其它信息 |
注意:shelf 单本书不包含阅读时长字段,时长必须靠 /book/getprogress 获取。书架书籍可能上百本,不能全量拉进度。
/book/getprogress(单本进度)
请求:{"api_name":"/book/getprogress","bookId":"3300035133","skill_version":"1.0.4"}
返回 data.book 关键字段:
| 字段 | 说明 |
|---|---|
bookId | 书籍 ID |
progress | 阅读进度百分比(0-100) |
readingTime | 总阅读时长(秒),用于"总阅读时长"过滤 |
updateTime | 最近阅读时间戳(作为卡片 last_read_time) |
chapterUid / chapterIdx | 当前阅读位置 |
recordReadingTime | 恒为 0,勿用(接口未返回真实值,早期误用导致过滤失效) |
聚合与过滤逻辑(weread-activity.php)
- 第一波并行请求
/readdata/detail?mode=monthly+/shelf/sync。 - 过滤
books[].secret=1的私密书籍与readUpdateTime<=0的未读书籍。 - 按
readUpdateTime降序取最近WEREAD_BOOK_CANDIDATE_LIMIT本(默认 24)作为候选池。 - 第二波并行请求候选池每本的
/book/getprogress(curl_multi并发,总耗时≈最慢单请求)。 - 过滤总阅读时长
< WEREAD_MIN_BOOK_READ_SECONDS(默认 1800 秒 = 30 分钟)的书;进度请求失败、无法确认时长的书同样过滤。 - 剩余按
readUpdateTime降序取前 3 本展示;不足 3 本时有几本显示几本,0 本显示"暂无公开阅读记录"。
关键实现点
- 时长过滤用
book.readingTime(总时长),不是recordReadingTime。 - 候选池 24 本保证"最近只点开几本书、真正读过的书排在更后面"时仍能凑满 3 本;实际数据下最近 24 本内通常有 4-6 本过 30 分钟。
- 进度失败即
readingTime=0,在阈值过滤下被丢弃(候选池有兜底,不因单本失败回退显示--)。 - 隐私规则:私密/未读书籍在排序与请求前过滤;
deepLink仅接受weread.qq.com及其子域的 HTTPS。 - 缓存:
usr/cache/weread_activity.json(6 小时)与永久兜底weread_activity_fallback.json。
可调配置(config.inc.php,均为可选)
define('WEREAD_API_KEY', '...'); // 必填,个人 API Key
define('WEREAD_SKILL_VERSION', '1.0.4'); // 可选,默认 1.0.4
define('WEREAD_MIN_BOOK_READ_SECONDS', 1800); // 可选,展示书籍的最小总阅读时长(秒),默认 1800请求示例
获取月度阅读统计
curl -s https://i.weread.qq.com/api/agent/gateway \
-H "Authorization: Bearer <key>" -H "Content-Type: application/json" \
-d '{"api_name":"/readdata/detail","mode":"monthly","skill_version":"1.0.4"}'同步书架
curl -s https://i.weread.qq.com/api/agent/gateway \
-H "Authorization: Bearer <key>" -H "Content-Type: application/json" \
-d '{"api_name":"/shelf/sync","skill_version":"1.0.4"}'查询单本进度(含总阅读时长)
curl -s https://i.weread.qq.com/api/agent/gateway \
-H "Authorization: Bearer <key>" -H "Content-Type: application/json" \
-d '{"api_name":"/book/getprogress","bookId":"3300035133","skill_version":"1.0.4"}'注意事项
- 参数必须拍平到顶层:包在
params里会报errcode=-2003 参数格式错误。 readingTime才是总阅读时长;recordReadingTime恒为 0。- 进度请求按候选池并发(24 个
curl_multi),不是串行,不会 24 倍延迟;只在冷缓存刷新时发生(6 小时一次)。 - 回包出现
upgrade_info或errcode != 0时本次刷新失败,回退读取 fallback 缓存。 readdata/detail里返回的readLongest[]只含本月读得最多的几本,不代表"最近阅读",勿用作过滤来源。- 卡片
deepLink只使用接口返回的 HTTPS 链接,host 必须为weread.qq.com或子域,不自行拼接。