大家好,我是王胖纸,Atlasnote的独立开发者。
这段时间,趁着 Vibe Coding 的间隙,我读完了一本很特别的电子书:Paul Graham 文章合集。
先说明一下,这并不是网上现成售卖的电子书,也不是某个平台上的整理版本,而是我用自己搭建的一套 Skills 工作流,把 Paul Graham 官网多年来的文章,自动抓取、整理、翻译,再最终打包成的一本 EPUB 电子书。
如果你长期关注创业、编程、投资和个人成长,Paul Graham 是一个很难绕开的人物。
他是程序员、作家、投资人,也是 Y Combinator 的联合创始人之一。早年他创办了 Viaweb,后来公司被 Yahoo 收购,成为 Yahoo Store;2005 年,他又与 Jessica Livingston、Robert Morris、Trevor Blackwell 一起创办了 Y Combinator。除此之外,Paul Graham 还是一位极具影响力的写作者——从 2001 年开始,他就在个人网站上持续发表文章,这些文章多年累积下来,已经成为互联网世界中一套非常独特的思想档案。
Paul Graham 的文章并不是那种看完就过去的博客流水账。他写创业,写编程,写写作,写财富,写好奇心,也写一个人如何找到真正值得长期投入的事情。很多人读他的文章,并不是为了追热点,而是为了反复回看、反复咀嚼。
问题在于:网页适合浏览,却不适合系统阅读。
如果只是临时看一篇文章,网页当然没有问题;但如果你真的想把这些内容集中起来,做长期阅读、标注、翻译、离线保存,甚至整理成一套自己的知识材料,那么一篇篇复制、粘贴、保存,就会变成一件非常繁琐的事情。
而这,恰恰是我觉得最适合交给 AI 和工作流去完成的任务。
所以我做的事情很简单:不是手工整理,而是把 Paul Graham 的文章从网上抓取下来,转成结构化的本地内容库,再进一步完成翻译、整理,最后打包成一本可以在阅读器里直接打开的 EPUB 电子书。
更重要的是,作为知识爱好者而言,这肯定不是我们想要抓取的唯一的内容,而任何需要重复三次以上的工作,都值得做成一个工作流。
不是写一个脚本,而是做一条内容生产流水线
过去做这件事,最直接的办法可能是:写一个 Python 脚本,把网页 HTML 下载下来,再用某个库转成 Markdown,最后用 Calibre 或 Pandoc 打包成 EPUB。
这样当然可以,但问题是,一旦文章数量变多,图片变多,网页结构不一致,或者后面还要翻译、做封面、重新出版,单个脚本很快就会变成一团难以维护的东西。
所以这个思路不是做一个“一次性脚本”,而是把整个过程拆成四个连续的 Skills:
web-to-markdown → batch-translator → book-cover-generator → epub-book-publish
这四个 Skill 分别负责一个阶段:
第一步,web-to-markdown 负责从网页抓取文章内容,把 Paul Graham 网站上的文章转换成标准 Markdown。它不只是保存正文,还会记录标题、来源链接、发布时间、作者、图片资源、抓取时间等信息。
第二步,batch-translator 负责批量翻译。如果我们希望把英文文章翻译成中文,它可以读取上一步生成的 Markdown 内容,保护代码块、链接、引用、frontmatter,再按章节或段落分块翻译。
第三步,book-cover-generator 负责生成图书封面。这里我们没有把书名直接交给生图模型,因为 AI 图片模型很容易把文字画错。正确做法是:先生成无文字背景图,再由程序把书名、副标题、作者名排版上去。
第四步,epub-book-publish 负责把文章、元数据、封面、目录结构、图片资源统一打包,生成最终 EPUB。
这条链路的核心价值是:每一步都有标准输入和标准输出。不是“这个脚本临时给那个脚本用”,而是每个 Skill 都可以独立运行,也可以串成完整出版流程。
第一步:从 Paul Graham 官网抓取文章
Paul Graham 的文章集中发布在个人网站上,官网有一个 essays 列表页,里面列出了他的文章标题和链接。([Paul Graham][2])
web-to-markdown 做的事情可以理解为:
读取文章列表
↓
并行抓取每篇文章
↓
提取正文和元数据
↓
下载图片
↓
转换成 Markdown
↓
生成 manifest.json 和质量报告
这里有一个很实际的问题:如果文章数量很多,而且每篇文章里还包含图片,串行下载会非常慢。所以我们在设计里加入了两层并行。
一层是文章级并行,比如同时处理 4 到 6 篇文章;另一层是图片级并行,比如一篇文章里有多张图片时,可以同时下载多张图片。
但并行不是越大越好。抓网页要尊重网站负载,也要避免触发 429、403 或超时。因此我们会设置 workers、delay、retry、timeout。目标不是暴力抓取,而是稳定、可恢复、可追踪。
最后输出的是一个内容归档包,大致长这样:
outputs/paul-graham-essays/
├── content/
│ ├── 001-article-title.md
│ └── 002-article-title.md
├── assets/
├── metadata/
├── manifest.json
└── reports/quality-report.json
这一步完成后,网页就不再只是网页,而变成了一个本地可管理的内容库。
第二步:是否翻译,取决于出版目标
如果目标是原文阅读,可以跳过翻译,直接进入 EPUB 打包。
如果目标是做中文版阅读包,就进入 batch-translator。它不会粗暴地把整个 Markdown 扔给模型,而是先保护 Markdown 结构,比如代码块、链接、frontmatter、URL 和内联代码。然后再分 chunk 翻译,最后恢复结构。
这样做的好处是:翻译后的文件仍然是干净的 Markdown,而不是一堆格式被破坏的文本。
翻译后的归档包依然保持标准结构:
translated-archive/
├── content/
├── assets/
├── metadata/
├── manifest.json
└── reports/
这意味着后面的封面生成和 EPUB 出版不需要重新猜路径,也不需要人工整理文件。
第三步:生成一本书该有的封面
一本电子书不一定必须有复杂封面,但如果我们希望它像一本真正可以收藏的阅读材料,封面就很重要。
我们的 book-cover-generator 不只是“生成一张漂亮图”。它会先根据书名、主题、类型、摘要生成一个结构化 brief,再决定风格、构图和视觉方向。
比如这本书可以叫:
也可以做成中文标题:
封面可以偏极简、理性、硅谷风,也可以偏出版物风格。关键是:背景图可以由 AI 生成,但书名和作者名必须由程序排版。这样才能保证文字清晰、准确、可读。
第四步:打包成 EPUB
最后一步是 epub-book-publish。
它读取前面生成的文章归档、封面图和元数据,然后自动生成章节、目录、导航文件、CSS 样式、图片资源,并打包成 EPUB。
最终输出类似:
outputs/paul-graham-epub/
├── paul-graham-essays.epub
├── manuscript.from-archive.json
├── index.md
└── reports/
├── publish-report.json
└── quality-report.json
这时候,我们就得到了一本可以放进 Apple Books、Kindle 阅读器、Calibre 或其他 EPUB 阅读器里的电子书。
这套方法真正重要的地方
我们搭出了一条可复用的内容生产流水线。
今天它可以处理 Paul Graham 的文章,明天也可以处理一个博客、一个文档站、一个公开课程页面,甚至一个系列化知识库。只要入口是网页,后面就可以进入同一条流程:
网页 → Markdown → 翻译 → 封面 → EPUB
这就是 Skills 工作流的价值:它不是帮我们完成一次任务,而是把一类任务变成可重复、可扩展、可发布的系统。
这也是 AI 工具真正有意思的地方,不是让 AI 替我们随便生成一点内容,而是让 AI 和代码一起,把原本分散、低效、手工化的知识整理过程,变成一套可执行的生产系统。
这真是一个美好的世界。
PS,出于版权考虑,这本书仅作为自己阅读和学习使用,就不在这里分享了。