语雀文档导出工具

2024年3月15日 · 1662 字 · 4 分钟 · 前端 Node 文档管理

语雀导出文档工具 (支持单独导出指定知识库)

初衷是之前一直用语雀作为主要文档管理工具(包括团队级文档),但随着量越来越大并且DIY的东西越来越多,再加上有些属于业务机密的逻辑记录,于是准备把语雀上的知识库,使用Node命令一键导出 Markdown 文档,再通过自建文档库的方式使用,这样就不用收到服务商的任何限制了,本篇主要记录工具用法。

计划

在评估了多种导出方案后,我准备选择了使用Node来模拟用户点击事件实现这一功能(因为直接调用API需要超级VIP才行)。Node的跨平台特性和强大的社区库(NPM)使得它成为处理此类任务的理想选择。通过编写一个简单的Node脚本来获取JSON源数据,并捕获返回值并将文档转换保存为Markdown格式(图片不用动,就用语雀的URL源),再搭配比如(Astro\Hugo️️\Docusaurus\Docsify)在本地进行文档管理和内网部署使用。

开源

但想到我肯定不是第一个吃螃蟹的人,那就GitHub搜了搜有几个热门的同质工具,差不多可以满足我的要求,这…, 那必须直接拿来就用了。

第一个是:官方的 exporter 工具 https://github.com/yuque/yuque-exporter
第一个是:普通用户都能直接用的 https://github.com/markyun/yuque-exporter

第二个感觉更符合我的初想,搭配Puppeteer使用起来也很简单,下面简单几步即可。

PS: 在使用这些工具之前,确保你的开发环境中已经安装了 Node.js 和 npm。这是使用 Node 脚本的基础。如果尚未安装,可访问 Node.js 官网 下载并安装。

示例

1. Mac 安装 Chromium (一个开源的浏览器项目,它提供了一个可以用于无头模式(无需图形界面)的浏览器环境)


brew install chromium

2.下载 exporter 工具

  • 模拟用户浏览器操作一篇一篇导出 markdown 文档
  • 按照知识库目录导出文档
  • 支持导出失败重试
  • 导出文档中的图片到本地
  • 替换文档中的图片链接

git clone https://github.com/markyun/yuque-exporter.git

npm install

3. 运行 node 脚本


# 第一次运行时,使用 USER + PASSWORD 登录 EXPORT_PATH 导出不用写
# USER=xxx PASSWORD=xxx node main.js
USER=xxx PASSWORD=xxx EXPORT_PATH=/path/to/exporter node main.js

# 登录一次后会保存 cookie,之后使用cookie登录
# node main.js
EXPORT_PATH=/path/to/exporter node main.js

4. 常见错误

如果这么简单的话,就不用我写记录了。直接看官方MD文档就行, 需要注意的(我是 M1 芯片 Mac 系统):

一般安装 npm install 这一步就会出错, Puppeteer 依赖的 Chromium 必须需要手动安装。设置跳过 PUPPETEER_SKIP_DOWNLOAD。

出错内容:

  puppeteer postinstall$ node install.js
  │ ERROR: Failed to set up Chromium r1108766! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download.
  │ Error: read ECONNRESET
  │ at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
  │ errno: -54,
  │ code: 'ECONNRESET',
  │ syscall: 'read'
  │ }

另外一个错误是: 因为跳过了 chromium 的安装, 需要手动指定 chromium所在路径,也就是 第一步 brew 安装的文件路径.

export CHROMIUM_EXECUTABLE_PATH=/Users/xx/Documents/chromium




// chromium 在mac上默认安装英特尔版本,如果想安装M1版本需要使用下面方式安装
PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM=1 npm install puppeteer

brew reinstall chromium



	// const page = await BrowserPage.getInstance();
	const browser = await puppeteer.launch({
		headless: true,
		executablePath: '/Applications/Chromium.app/Contents/MacOS/Chromium',

	}); 
  // true:not show browser

5.运行 node 脚本 成功反馈

node main.js 如果成功后,会显示 如图所示内容就表示下载成功了.

a

扫描完成后,会下载全部内容

a1

6.支持单独导出指定知识库

如果不想下载全部知识库,可以在这里根据api获取对应知识库的ID,限制。

ps: 因为有的同学,知识库内容太多,可以在 getAllBooks 函数中,拿到 bookData 数据后进行判断,只下载需要的 books 知识库。

// 直接硬编码也可以
if (object.books[i].id ===48016029) {}

完整版


// 调用处
	const booksId=882422;
	const books = await getAllBooks(page,booksId);
  
// 可以自己DIY 
export async function getAllBooks(page,booksId) {
    const books = [];
    const response = await page.goto('https://www.yuque.com/api/mine/book_stacks', { waitUntil: 'networkidle0' });
    const data = await response.text();
    const parser = jsonstream.parse('data.*');
    
    const bookData = await new Promise((resolve) => {
        const parsedBooks = [];
        parser.on('data', (object) => {
            parsedBooks.push(object);
        });
        parser.on('end', () => {
            resolve(parsedBooks);
        });
        parser.end(data);
    });

    for (const object of bookData) {
        for (let i = 0; i < object.books.length; i++) {
            if (booksId && object.books[i].id ===booksId) {
                const book = new Book(object.books[i].id, delNonStdChars(object.books[i].name), object.books[i].slug);
                console.log("book",book);
                book.root = await getBookDetail(page, book);
                book.user_url = object.books[i].user.login
                books.push(book);  
            }
            
        }
    }

    console.log(`Books count is: ${books.length}`);
    return books;
}

通过 https://www.yuque.com/api/mine/book_stacks 接口获取 全部 bookData 内容,拿到想要的 object.books[i].id。

通过https://www.yuque.com/api/catalog_nodes?book_id=173556 +id 可以得到当前知识库的全部文章列表 getBookDetail 内容。(这样相当于,如果你想下载别人开放的知识库,也是可以DIY的)

下载图片 export-image

// Mac系统 下载图片 python3 export-image.py

// 需要先安装 requests pip3 install requests

语雀文档 导出后的格式处理

url 后面跟上下方的参数,也可以直接获取单篇文档的markdown格式。

/markdown?plain=true&linebreak=false&anchor=false
?view=doc_embed&from=kb&from=kb&outline=1&title=1

替换语雀图片后缀:

这个步骤将会删除保存的图片的多余部分,使图片能够正常显示。这个方法无需运行脚本,只需要使用 Markdown 编辑器进行简单的文本替换操作即可解决问题。

#averageHue=[a-zA-Z0-9\-&=%\.]*

正侧替换为   空 


<!-- 同时项目的HTML头,添加下面的信息 -->

["meta", { name: "referrer", content: "no-referrer" }],