零代码基础?AI 助你免费“搬空”语雀知识库

4 阅读4分钟

零代码基础?AI 助你免费“搬空”语雀知识库

背景:语雀的 API 导出功能和高级 API 调用限制或收费。对于想要迁移知识库、做本地备份的开发者来说,这无疑增加了一道门槛。本文记录了我如何通过与 AI 结对编程,在不写一行代码的情况下,从零构建一个功能强大的语雀全量知识库爬虫

🚀 需求起因

我想把语雀上的某个公开知识库(或者我自己的私有库)完整迁移下来,最好是 Markdown 格式,图片也要下载到本地,保持原汁原味的目录结构。

但是遇到了几个痛点:

  1. API 门槛:语雀官方 API 有调用限制,且部分高级功能需要会员。
  2. 手动复制:文档太多,手动复制粘贴是不可能的。
  3. 图片防盗链:Markdown 里的图片链接是语雀的,直接复制出来可能会失效。

于是,我找到了 AI 助手(CAN),开始了这段奇妙的旅程。


🛠️ 第一阶段:从单页爬取开始

:帮我生成一个 node 爬虫脚本,爬取某个语雀页面的 html。

AI (CAN)

“没问题!考虑到语雀是单页应用(SPA),我推荐使用 Puppeteer 来模拟浏览器行为。”

AI 迅速生成了一个基于 Puppeteer 的脚本。但在运行时,我们立刻遇到了第一个拦路虎——401 Unauthorized

问题分析:语雀的很多文档是私有的,或者是需要登录态才能访问的。

解决方案:AI 建议在代码中注入 Cookie。我只需要在浏览器登录后复制 Cookie 填入,脚本就能成功访问页面了。


🔄 第二阶段:逻辑升级与 Markdown 获取

:给了 AI 一个现成的 Python 脚本逻辑作为参考,希望它能复刻其功能:直接获取 Markdown 源码,而不是爬 HTML 再转换。

AI (CAN)

“收到!我会重构代码。利用 Puppeteer 获取页面上下文中的 book_idslug,然后直接调用语雀的内部 API /api/docs/{slug} 获取 Markdown 源码。”

这次升级非常关键:

  1. 不再解析 HTML:直接拿 Markdown 源码,格式最完美。
  2. 图片本地化:AI 自动写了解析 Markdown 图片链接的正则,把图片下载到本地 images/ 目录,并替换 Markdown 中的链接为相对路径。

📚 第三阶段:全量知识库爬取

:光爬单页不够,我要爬整个知识库!

AI (CAN)

“明白!我会利用 Puppeteer 解析知识库首页的 window.appData,拿到完整的目录结构(TOC),然后递归下载所有文档。”

AI 不仅实现了全量爬取,还贴心地做到了:

  • 目录还原:按照语雀左侧的目录树,在本地创建对应的文件夹。
  • 生成 SUMMARY.md:生成 GitBook 风格的目录文件,方便后续导入 GitBook 或其他文档工具。

⚡ 第四阶段:工程化与性能起飞

:脚本跑得太慢了,能不能并发?另外控制台打印太乱了,能不能优雅一点?

AI (CAN)

“安排!

  1. 引入并发:使用 p-limit 控制并发数,下载速度提升 5 倍!
  2. 工程拆分:将代码拆分为 config.jsutils.jscrawler.js,结构清晰。
  3. 进度条:引入 cli-progress,实时展示下载进度,看着进度条跑完简直解压。”

这一步,脚本从一个“玩具”变成了一个“工具”。AI 甚至考虑到了反爬策略,在请求之间加入了随机延迟。


🧹 第五阶段:细节打磨

:发现下载了很多空的 .md 文件,原来是那些只有子目录没有内容的节点。

AI (CAN)

“小问题。我加个判断,如果 API 返回内容为空,就不生成文件,同时在 SUMMARY.md 里把它标记为纯文本节点。”


🎁 最终成果

现在的项目结构是这样的:

.
├── src/
│   ├── config.js          # 配置 Cookie 和并发数
│   ├── crawler.js         # 核心爬虫逻辑
│   └── utils.js           # 工具函数
├── index.js               # 入口
└── download/              # 你的知识库就在这里!

使用方法

  1. npm install
  2. src/config.js 填入你的 Cookie。
  3. node index.js
  4. 起身喝杯咖啡,回来收货。

💡 总结

如果你也有类似的需求,不妨试着让 AI 帮你写个脚本。Coding is fun, especially with AI!

github 仓库:github.com/xiyueyezibi…