1. 为什么飞书文档一定要折腾成markdown
飞书文档给我的第一印象是“写起来很舒服”。界面干净,多人协作顺手,权限粒度细,很多团队干脆把它当成知识库和项目文档中心来用。但一旦牵扯到“把内容拿出去”:发到自己的博客、扔进Git仓库做版本管理、迁到别的知识库平台,问题就来了。飞书官方导出的docx、pdf格式,往往带着一堆平台自有的样式冗余,粘贴到markdown编辑器里七零八落,图片链接乱飞,列表缩进全崩。如果你恰好维护着一套基于markdown的内容工作流,中间的格式转换成本会高到让你怀疑人生。
说白了,markdown是内容流通里的通用格式。你的网站能渲染它,Obsidian能管理它,GitHub、GitLab、Gitee能直接预览它,Hugo、Hexo、VitePress这些静态建站工具更是把markdown当作默认数据源。把飞书文档转成markdown,等于把写好的内容从“平台私有格式”解放成“任何系统都能读的纯文本”。这也是feishu2md这类工具存在的根本理由:它把飞书文档底层的block数据结构,逐块翻译成标准的markdown语法,而不是模拟人肉复制粘贴。
实际操作中,“把飞书文档内容拿出去”的常见方案大概有三种:
- 直接复制粘贴正文:适合一次性搬几段纯文字,但图片存活率很低,表格和代码块经常碎成一团。
- 官方导出后再用其他工具转:先转docx、再转markdown,步骤多、损耗大,列表和标题层级容易变形。
- 用feishu2md直接拉取转换:标题、列表、代码块、图片、表格、公式都能保留成markdown实体,还支持批量处理。
我最终选择feishu2md,就是因为它避开了一条弯路:不经过任何中间格式,直接从飞书API拿内容转成markdown。这篇博文想解决的,也恰恰是“怎么顺利把飞书文档转换成markdown”和“转出来的文件怎么用起来”这两件事。它的目标读者很明确:维护技术博客的写作者、要给团队做文档迁移的知识库管理员、习惯把所有内容沉淀在本地markdown仓库里的效率工具党。
2. feishu2md的准备工作:应用权限与配置
很多第一次用feishu2md的人会想当然:把文档链接丢进去就能出markdown。真不是这样。feishu2md不是爬虫,不靠抓网页HTML解析,它调用的是飞书开放平台的文档API。既然是API调用,就必须先让程序拥有“读取你文档”的权限。我实际用下来,十次转换失败里,至少八次都是权限配置的问题。
2.1 在飞书开放平台创建自建应用
第一步去飞书开放平台的开发者后台,创建一个“企业自建应用”。名字随意,比如“文档转换机器人”,然后在应用凭证页面找到App ID和App Secret,这两串字符串是后续用来换取调用凭证的关键凭据,相当于程序的账号密码。
这里有一个容易卡住的细节:如果你的飞书账号登录不了开放平台,通常是因为账号没有被赋予“开发者”权限。个人版飞书或部分受限企业账号,需要找团队管理员在飞书管理后台把你的账号添加上开发者角色,否则浏览器会直接提示无权限进入。另外,自建应用一般不需要大费周章走发布商店流程,只要在应用后台完成配置就行。
2.2 开通权限、发布版本、把文档分享给机器人
创建应用只是一半,另一半是给它开权限。飞书开放平台的权限体系很严格,默认情况下新应用什么都读不了。要在“权限管理”页面搜索并开通以下几类只读权限:
- docx相关权限,用来读取文档正文内容。
- drive相关权限,用来访问云空间文件。
- 图片、媒体资源相关权限,用来下载文档内嵌的图片。
不同版本的权限项名称有细微差别,搜索“docx”和“drive”前缀的权限,把和“查看”“读取”“下载”相关的只读权限都勾上总没错。开通权限之后,必须再“创建版本”并发布,发布审批通过或者管理员同意之后,权限才真正对所有API调用生效。很多人配完权限直接跑命令,结果还是401、403,就是因为漏了“发布”这一步。
紧接着的另一个关键动作,是把目标文档分享给应用对应的机器人。文档右上角点“分享”,输入自建应用机器人的名称,选择“可阅读”权限。feishu2md是以应用身份去读文档的,如果应用对该文档没有访问权,哪怕你在权限管理里开了全量只读权限,单篇文档依然读不出来。这个坑我踩过:全局权限开了,批量转的时候部分文档被拒,一查才发现那些文档从来没分享给机器人。
2.3 安装feishu2md并配置环境变量
安装很直接,工具是Python写的,pip直接装:
pip install feishu2md装完把App ID和App Secret塞进环境变量:
export FEISHU_APP_ID="cli_xxxxxxxxxxxx" export FEISHU_APP_SECRET="xxxxxxxxxxxxxxxx"如果你的文档在海外版Lark上,记得加一行域名配置:
export FEISHU_DOMAIN="larksuite.com"国内飞书默认走feishu.cn,不用额外设置。配置完成后,建议先拿一篇短文档测试,能顺利生成md再往大文档上跑。
这里给一个实用建议:环境变量在终端里设置,只对当前会话生效,关掉终端窗口就没了。与其每次敲一遍,不如写进~/.zshrc或~/.bashrc,或者做一个.env文件配合direnv之类的工具自动加载。我的习惯是单独维护一个feishu工具目录,里面放着环境变量文件和批量转换脚本,换新电脑部署也能快速恢复。
3. 转换实操:从命令行到产出md文件
3.1 单个文档转换
跑命令时参数很简单,直接把飞书文档链接丢进去:
feishu2md https://your-domain.feishu.cn/docx/xxxxx配置正确的话,工具会解析URL里的文档token,通过API拉取文档的block列表,再逐块翻译成markdown。完成后,当前目录下会出现一个以文档标题命名的.md文件,文档里用到的图片通常会被下载到同名图片目录,并在md中用相对路径引用。
我想强调一个体验:转换结果的价值主要体现在“结构”上。正常的技术方案文档,转换后#、##、###层层分明,正文里的无序列表、有序列表、任务列表、引用块、代码块都有对应的markdown语法。拿到md以后,我习惯先用Typora或者VS Code的preview打开扫一眼,确认标题层级没有崩坏、代码块没有散架,再继续后续内容加工。
3.2 批量转换多个文档
飞书文档一多,逐个手动跑命令就不划算了。feishu2md本身能处理单个链接,批量转换我一般在bash里写循环,把链接列表放进一个txt文件:
for url in $(cat doc_urls.txt); do feishu2md "$url" done也可以更稳一点,用Python脚本逐行读取URL,每转换一个文件加个短暂间隔,避免触发接口限流:
import subprocess import time with open("doc_urls.txt", "r") as f: urls = [line.strip() for line in f if line.strip()] for url in urls: print(f"converting {url}") subprocess.run(["feishu2md", url]) time.sleep(1)这样处理几十个文档也就几分钟的事。转换后的md文件名来自文档标题,文件名里可能有空格和特殊字符,建议批量重命名成“日期-标题.md”这种格式,方便归档和排序。我在迁移整套团队知识库时,就先导出所有文档链接,再用上面这段脚本跑了一轮,之后按目录分类归档。
3.3 转换后的内容长什么样
我把一份包含标题、表格、代码块、公式、图片的飞书文档实际转了一遍,结果大致是这样的:
- 标题:飞书多级标题对应markdown的多级#,这是转换最标准的环节。
- 列表:无序列表变成-开头,有序列表变成1. 2. 3.,任务列表变成- [ ]和- [x]。
- 代码块:语言类型标注基本能保留,比如
python,看着很干净。 - 表格:普通表格能转成markdown表格;带有合并单元格的复杂表格,会退化成简化结构,需要后期手补。
- 公式:飞书文档里的块级公式,转出后通常保留LaTeX格式,也就是markdown里$$包裹的那段内容。
- 图片:默认下载到本地,md内用相对路径引用,不会出现外链过期的问题。
整体来看,纯正文内容的转换可以做到“基本无损”,但特别复杂的排版布局确实会有压缩。这不是工具的问题,而是markdown这种纯文本格式的固有边界:它本身就只承载结构化内容,不承载精细排版。
4. 转换结果不完美时怎么补救
4.1 图片路径:本地引用和相对路径
整个转换过程中,图片信息是最好处理的,但也是最容易翻车的。常见情况是:文档里引用了外链图片,转换后md里是一堆http链接,一旦外链失效,图片全挂。另一种情况是应用权限里没开图片下载,转换后图片全是空的。
我的补救套路是统一做“图片本地化”:写一段Python脚本,遍历md里的标签,把URL对应的图片下载到本地images目录,再把md里的引用地址替换成相对路径。核心逻辑不复杂:
- 用正则找出所有图片URL。
- 根据原文档的目录结构,按序号保存图片。
- 替换md文本中的路径为相对路径。
这段脚本可以反复执行,换一批文档照样用。如果你追求极致,还可以反过来把图片传到图床或对象存储,再用完整URL替换,静态博客场景下也不会拖慢仓库体积。说到底,图片路径这件事要尽早定规矩:要么全本地化,要么全远程,混着用最容易出问题。
4.2 复杂表格和公式的降级处理
飞书文档里出现合并单元格非常常见,但markdown原生不支持表格合并。遇到这类表格,转换工具大概率会把它们变成一堆平铺文本,阅读体验很差。我的处理方案分两种情况:如果表格本身就是文档核心数据,那我直接把原文档里的表格截图保存到md同目录,并在md里注明“详见原表截图”,保证信息不丢;如果表格只是辅助说明,就手动精简成几行markdown表格甚至列表,反而更清晰。
公式方面,如果你用的渲染器支持LaTeX公式,转出来的公式能直接显示。Typora、Obsidian、Pandoc、MathJax扩展这些主流工具默认都支持markdown公式渲染,这也是为什么热搜里总有人问“markdown数学公式插件”。但要注意:markdown里的_、*、^这类符号和LaTeX语法偶有冲突,公式在转换后不一定被自动包裹在$或$$里。建议拿到md以后,写个脚本批量检查是否有裸公式——特别是那些以“\begin{aligned}”或“\frac”开头的行,如果没被公式标签包裹,手动加上即可。
4.3 特殊元素和能力边界
飞书文档不只有纯文本。脑图、多维表格、画板、投票这一类结构化组件,feishu2md读取的是docx的block结构,所以它能应付常规段落,但面对脑图和多维表格,转换结果可能只是纯文本描述,甚至直接丢失。
我的经验是:转换之前先在飞书里给这些特殊元素做截图,把截图保存到本地,转换完成后在md末尾挂上图片链接;或者先手动把脑图、思维导图内容改成大纲列表,把多维表格改成普通markdown表格再做转换。另一个特别容易踩的坑是超长文档。飞书API对单次拉取的block数量有限制,几千行的巨型文档经常只转出一半内容。遇到这种情况,先在飞书里把文档拆成几个子文档,逐个转换,最后在markdown里手动合并,比硬跑一次要可靠得多。我的习惯是超过两千行的文档一律先拆后转。
5. 把转好的markdown放进自己的内容工作流
5.1 在博客和知识库里的用法
转出来的markdown不应该是囤积在硬盘里的死文件,它要进入你的内容生产和发布链路。我周围朋友最常见的用法有这么几种:
- 放进Git仓库,用Hugo、Hexo或VitePress构建成静态博客。
- 导入Obsidian、Logseq做个人知识管理,配合双链和标签继续加工。
- 用Pandoc继续转成PDF、Word,给不习惯看md的同事交付。
- 导入语雀、Notion这类支持markdown导入的平台,实现跨平台迁移。
如果你在Linux终端工作,阅读markdown也很方便,装一个glow或mdcat,终端里就能舒服地渲染标题、列表、代码块,跟看排版文档一样顺手,根本不用打开图形界面。
5.2 飞书内容嵌入自己网站的几种方式对比
很多朋友私信问“怎么把飞书云文档内容嵌到自己网站上”。这件事有几种靠谱做法,各有取舍:
- iframe嵌入官方分享链接:实现最快,飞书文档现成的分享链接加上iframe标签就能用,但搜索引擎几乎不会收录,样式也没法改。
- 外链跳转到飞书:直接放一个“查看完整文档”的按钮,跳转过去体验完整,但用户跳出感强。
- 调用飞书开放API做实时渲染:文档内容实时从飞书拉取,自己写前端加载block数据,自由度最高,开发成本也最大。
- feishu2md转markdown后同步发布:转出来的md进入静态建站流程,内容完全可控、利于SEO、便于二次加工,是目前我实测最省心的方案。
我的判断标准很简单:如果内容需要长期反复更新,并且要出现在自己的网站域名下,就别把鸡蛋全放在飞书分享链接里。让飞书做“编辑后台”,让markdown做“发布中间层”,网站的页面生成完全由自己把控。这样飞书的协作体验保住了,网站内容的可控性也保住了。
5.3 团队文档同步与备份
扩展到团队协作场景,一套完整的工作流可以这样设计:团队在飞书文档里协作写方案,每天凌晨通过脚本批量拉取全部指定文档,转成markdown后提交到Git仓库。仓库背后再接一个持续构建任务,网站内容自动跟着更新。这个流水线同时完成了三件事:内容发布、知识库更新、历史版本备份。
权限上的好处也值得一提:应用只有只读权限,拉取过程不会误改原文档;本地仓库的Git历史则相当于一份完整的文档演进记录,每一版变化都有据可查。团队里有人误删了文档,或者想回溯某个方案的上个版本,直接从Git里恢复就可以了,不必在飞书管理后台翻找恢复记录。
说实话,这套流程跑通以后,我就不太能接受“从飞书复制粘贴到公众号再调格式”这种笨办法了。飞书在我这里变成了内容产生的源头,而不是内容的终点站。
最后分享几个我实操中总结的经验。第一,权限配置完成后,一定要先拿一个小文档试跑,确认能生成md,再整批操作,否则批量跑一半报错,会浪费大量排查时间。第二,图片路径的问题尽量用脚本批量解决,别手动改,尤其是几十篇文档的场景。第三,转换完成不等于交付完成,每次拿到md后的检查清单——标题层级、代码块语言标注、公式包裹、图片是否本地化——都花几十秒扫一遍,能省去后面发布时的很多麻烦。如果你手里也有大量飞书文档需要迁移或备份,哪怕只是个人笔记的整理,这个思路都可以直接拿过去用,跑通之后“复制链接、跑命令、拿md”的三步操作会成为你最顺手的日常。