开源仓库地址:github.com/WANGXIN-567… (如果这个工具对你的深度学习与知识库整理有帮助,欢迎点亮一颗 Star ⭐ 支持!)
一、背景与痛点:为什么我决定自己造轮子?
平时在精读专业书籍、历史典籍或中医经典(比如《伤寒论》解读)时,我有三个强烈的个人学习需求:
- 全文检索与双链笔记:希望将整本书无损导出为干干净净的 Markdown,放进 Obsidian / Notion 建立个人知识库;
- iPad 大字号手写批注:希望导出一份排版考究、带侧边栏书签大纲(Outline)的 大字号精排 PDF(正文用温润的苹方,核心引文/古籍条文用华文楷体);
- 跨设备阅读:同时生成一份带完整目录树与原书高清插图的 标准 EPUB。
然而,在尝试了市面上现有的几款微信读书 Web 端导出脚本后,我发现它们在实际使用中普遍存在两个致命问题:
- 痛点 1:悄无声息地漏掉全书 35%~45% 的内容 比如一本 21 万字、包含 398 条原文的书,用传统脚本跑完居然只有 12 万字、217 条原文,每一章的下半部分都莫名其妙“蒸发”了。
- 痛点 2:跨章或短页文字交错乱码、原书排版层级全部丢失 导出来的文本要么两页文字穿插在一起,要么标题、引文、正文糊成一团,还经常因为页面折行把一句话切成两段。
为了彻底解决这些问题,我深入排查了微信读书 Web 端的渲染机制,并动手写了这个开箱即用的开源工具 —— weread-book-exporter。
二、技术复盘:为什么传统脚本会漏掉 40% 的字?
众所周知,微信读书 Web 端为了防止简单的 DOM 爬虫,正文字体并不是直接写在 HTML DOM 节点里的,而是通过 <canvas> 画布调用 CanvasRenderingContext2D.prototype.fillText 动态绘制出来的。
大多数基于 Playwright / Puppeteer 的抓取脚本,思路都是在页面初始化时 Hook fillText,然后不断模拟按下方向键 ArrowRight 翻页。
1. 罪魁祸首:上下滚动模式(isNormalReader)的虚拟画布分片
当浏览器处于默认的**上下滚动模式(isNormalReader)**时:
- 微信读书会将一个章节渲染在一个高度达到
17,000px+的超长虚拟滚动容器里; - 但出乎意料的是,它并不会一次性把整章绘制到 Canvas 上,而是只绘制当前视口附近的 上半部分(约前 3,500~4,000 字);
- 此时如果你直接触发
ArrowRight(下一章/下一页),阅读器不会替你向下滚动加载剩余分片,而是直接跳到了下一章的开头!结果就是每一章的下半截全部被静默丢弃。
2. 破局方案:强制锁定双栏水平模式 + 帧序列与分栏坐标切分
在 weread-book-exporter 中,我做了一套完整的底层改造:
(function() {
window.__wr_chars = [];
window.__wr_seq = 0;
// 1. 拦截画布大面积重绘,递增帧序列号 seq
var origClear = CanvasRenderingContext2D.prototype.clearRect;
CanvasRenderingContext2D.prototype.clearRect = function(x, y, w, h) {
if (w > 100 && h > 100) window.__wr_seq++;
return origClear.apply(this, arguments);
};
// 2. 拦截文字绘制,同时记录文本、坐标、字体字重、左右分栏及帧序列号
var origFill = CanvasRenderingContext2D.prototype.fillText;
CanvasRenderingContext2D.prototype.fillText = function(text, x, y) {
if (text && text.trim()) {
var st = (this.canvas && this.canvas.getAttribute('style')) || '';
var side = st.includes('right:') ? 1 : 0;
window.__wr_chars.push({
t: text,
x: Math.round(x * 10) / 10,
y: Math.round(y * 10) / 10,
f: String(this.font),
side: side,
seq: window.__wr_seq
});
}
return origFill.apply(this, arguments);
};
})();
配合以下三步策略,实现了 100% 零漏字抓取:
- 自动检测并切换至双栏翻页模式(
isHorizontalReader):在双栏模式下,每次按ArrowRight严格前进一个双栏视口(左页 + 右页),绝不跳过任何虚拟分片; - 按
(seq, side)原子化切分单页:过去很多脚本只按y坐标排序,一旦遇到左栏满页、右栏只有半页(或跨章重绘),左右两栏相同y坐标的字就会拼成同一行乱码。现在通过seq(重绘帧)+side(左/右栏)精准隔离每一单页,彻底根治乱序; - 利用
ctx.font还原原书排版语义:>= 24.5px→ 自动识别为章节/小节标题(支持跨行长标题自动合并);22.0px ~ 24.5px→ 识别为核心引文 / 古籍条文;bold 18px→ 二次语义判别区分独立重点段落与行内加粗,并自动拼接被画布折行打断的句子;18px→ 现代正文段落。
三、出版级多格式导出引擎:PDF / EPUB / Markdown 一键生成
抓取完完整章节与原书高清插图后,export_book.py 会一键生成三种高颜值格式:
1. 大字号「苹方 + 楷体」精排 PDF
专为平板批注与深度阅读设计:
- 双字体黄金搭配:现代解读正文采用 13.2pt 苹方字体(PingFang SC) +
1.95倍行距;古籍条文/核心引文采用 14.8pt 华文楷体 + 宣纸米底色卡片 + 朱砂红编号徽章; - 完整导览体验:自动生成封面页、双栏可点击跳转目录页、PDF 阅读器侧边栏章节书签大纲(Outline),以及带页码的页眉页脚。
2. 双字体标准 EPUB
- 内嵌多字体 CSS 样式表与全部原书插图,在 Apple Books、Kindle 或阅读器中打开即享双字体排版。
3. 纯净 Markdown(直通 Obsidian / Notion)
- 自动将引文转换为标准
> **引文**引用块,去除多余 HTML 标签污染,完美适配 Obsidian 双链笔记与全文检索。
四、快速上手(只需两行命令)
1. 克隆仓库并安装依赖
git clone https://github.com/WANGXIN-567/weread-book-exporter.git
cd weread-book-exporter
pip install -r requirements.txt
playwright install chromium
2. 抓取并导出全书
在微信读书网页版打开你已购或会员期内的书籍,复制地址栏末尾的书籍 ID(即 https://weread.qq.com/web/reader/<book_id> 中的 <book_id>):
# 第一步:启动浏览器抓取全书章节与插图(首次运行扫码登录,状态自动持久化在本地)
python crawl_weread.py <book_id>
# 第二步:一键生成精排 PDF、EPUB 与 Markdown
python export_book.py <book_id>
五、开源地址与致谢
项目已在 GitHub 完全开源(MIT 协议): 👉 github.com/WANGXIN-567…
注:本项目仅用于个人学习、无障碍大字号阅读辅助与前端 Canvas 渲染技术交流,请支持正版阅读,仅对个人合法拥有阅读权限的书籍使用。
如果你也常在微信读书上看书、做 Obsidian 笔记或用 iPad 批注 PDF,欢迎去 GitHub 点亮一颗 Star ⭐,有任何建议或需求也欢迎提 Issue 交流!