本项目提供飞书云文档/知识库的完整导出解决方案,支持:
- 将飞书知识库导出为Markdown格式
- 自动下载并关联图片、附件等媒体资源
- 保留原始文档结构和格式
- 与Dify知识库无缝集成
- 预留多模态扩展接口
- 完整结构保留:导出时保持原有的目录层级结构
- Markdown格式:将飞书文档转换为标准Markdown
- 媒体资源下载:自动下载图片、文件等附件并更新引用路径
- 批量导出:支持导出整个知识库或单个文档
- 元数据管理:生成完整的元数据索引文件
| 类型 | 支持状态 |
|---|---|
| 新版文档(docx) | ✅ 完整支持 |
| 旧版文档(doc) | |
| 电子表格(sheet) | 🔗 引用链接 |
| 多维表格(bitable) | 🔗 引用链接 |
| 思维笔记(mindnote) | 🔗 引用链接 |
- ✅ 标题(1-9级)
- ✅ 段落文本(加粗、斜体、删除线、下划线、行内代码)
- ✅ 有序/无序列表
- ✅ 待办事项(checkbox)
- ✅ 代码块(支持语言标识)
- ✅ 引用块
- ✅ 分割线
- ✅ 表格
- ✅ 图片(自动下载)
- ✅ 文件附件(自动下载)
- ✅ 高亮块/提示块
- ✅ 公式(LaTeX)
- ✅ @提及(用户/文档)
- ✅ 链接
- 导出文档自动导入Dify
- 增量同步支持
- 元数据关联
pip install -r requirements.txt创建 .env 文件:
# 飞书应用配置
FEISHU_APP_ID=your_app_id
FEISHU_APP_SECRET=your_app_secret
FEISHU_VERIFICATION_TOKEN=your_verification_token
# Dify配置(可选,同步到Dify时需要)
DIFY_API_KEY=your_dify_api_key
DIFY_API_URL=https://api.dify.ai/v1
DIFY_DATASET_ID=your_dataset_id确保你的飞书应用已开通以下权限:
wiki:wiki:readonly- 知识库只读权限docx:document:readonly- 文档只读权限drive:drive:readonly- 云空间只读权限
# 列出所有可访问的知识库
python export_wiki.py list-spaces
# 列出知识库中的节点
python export_wiki.py list-nodes <space_id>
# 导出整个知识库
python export_wiki.py export-wiki <space_id> -o ./exports
# 导出单个文档
python export_wiki.py export-doc <document_id> -o ./exports# 列出云盘空间(我的空间、共享空间)
python export_wiki.py list-drive
# 列出云盘文件夹内容
python export_wiki.py list-drive-folder <folder_token>
# 递归列出文件夹所有内容
python export_wiki.py list-drive-folder <folder_token> -r
# 导出我的空间
python export_wiki.py export-my-space -o ./exports
# 导出指定云盘文件夹
python export_wiki.py export-drive-folder <folder_token> -o ./exports
# 导出所有云盘空间(我的空间 + 共享空间)
python export_wiki.py export-all-drive -o ./exports
# 仅导出我的空间,不包含共享空间
python export_wiki.py export-all-drive --no-shared -o ./exportsexport-wiki <space_id> [选项]
-o, --output DIR 输出目录 (默认: ./exports)
-p, --parent-token 起始父节点token
--no-media 不下载媒体文件
--flat 不保留目录结构
--raw-content 使用raw_content API(更快但格式受限)
-c, --concurrency N 下载并发数 (默认: 5)
-v, --verbose 显示详细日志
export-my-space [选项]
-o, --output DIR 输出目录 (默认: ./exports)
--no-media 不下载媒体文件
--flat 不保留目录结构
--raw-content 使用raw_content API
-c, --concurrency N 下载并发数 (默认: 5)
export-drive-folder <folder_token> [选项]
-n, --name NAME 导出名称 (默认: 云盘导出)
-o, --output DIR 输出目录 (默认: ./exports)
--no-media 不下载媒体文件
--flat 不保留目录结构
--raw-content 使用raw_content API
-c, --concurrency N 下载并发数 (默认: 5)
export-all-drive [选项]
-o, --output DIR 输出目录 (默认: ./exports)
--no-my-space 不包含我的空间
--no-shared 不包含共享空间
--no-media 不下载媒体文件
--flat 不保留目录结构
--raw-content 使用raw_content API
-c, --concurrency N 下载并发数 (默认: 5)
from app.feishu import WikiExporter, ExportConfig
# 配置导出选项
config = ExportConfig(
output_dir="./exports",
download_media=True,
preserve_structure=True,
generate_index=True,
generate_metadata=True,
)
# 创建导出器
exporter = WikiExporter(config)
# 列出知识库
spaces = exporter.list_spaces()
for space in spaces:
print(f"{space.space_id}: {space.name}")
# 导出知识库
result = exporter.export_wiki_space("your_space_id")
print(f"导出成功: {result.exported_docs} 个文档")
# 导出云盘我的空间
drive_result = exporter.export_my_space()
print(f"导出成功: {drive_result.exported_files} 个文件")
# 导出云盘指定文件夹
drive_result = exporter.export_drive_folder("folder_token", "文件夹名称")
print(f"导出成功: {drive_result.exported_files} 个文件")
# 导出所有云盘空间
results = exporter.export_all_drive_spaces(
include_my_space=True,
include_shared_space=True
)
for result in results:
print(f"{result.space_name}: {result.exported_files} 个文件")from app.feishu import WikiExporter
exporter = WikiExporter()
result = exporter.export_single_document("document_id", "./output")
if result.success:
print(f"文件保存到: {result.markdown_path}")from app.dify import DifyKnowledgeSync
# 初始化同步服务
sync = DifyKnowledgeSync()
# 导入导出目录
result = sync.sync_from_export("./exports/your_wiki")
print(f"导入成功: {result.created} 个文档")
# 或导入单个文件
doc_id = sync.import_markdown_file("./exports/doc.md", "文档名称")exports/
└── 知识库名称/
├── README.md # 索引文件
├── metadata.json # 元数据
├── 文档1.md
├── 文档2.md
├── 子目录/
│ ├── 文档3.md
│ └── assets/ # 该目录的媒体文件
│ ├── image1.png
│ └── file.pdf
└── assets/ # 根目录的媒体文件
├── image2.jpg
└── attachment.zip
系统预留了多模态处理接口,后期可扩展:
from app.feishu.exporter import MultimodalExportInterface
# 图片OCR
text = interface.extract_image_text("image.png")
# 音频转文字
text = interface.extract_audio_text("audio.mp3")
# 视频转文字
text = interface.extract_video_text("video.mp4")lark/
├── export_wiki.py # 命令行入口
├── config.yaml # 配置文件
├── requirements.txt # Python依赖
├── .env # 环境变量(需创建)
├── app/
│ ├── config.py # 配置管理
│ ├── feishu/
│ │ ├── api_client.py # 飞书API客户端基础
│ │ ├── wiki_service.py # 知识库服务
│ │ ├── document_service.py # 文档服务
│ │ ├── block_converter.py # Block转Markdown
│ │ ├── media_manager.py # 媒体资源管理
│ │ ├── exporter.py # 知识库导出服务
│ │ └── cli.py # 命令行工具
│ └── dify/
│ ├── client.py # Dify API客户端
│ └── knowledge_sync.py # 知识库同步服务
├── examples/
│ └── export_example.py # 使用示例
└── exports/ # 默认导出目录
┌─────────────────────────────────────────────────────────┐
│ 飞书知识库 │
│ (Wiki Space / Cloud Documents) │
└──────────────────────┬──────────────────────────────────┘
│
│ RESTful API
▼
┌─────────────────────────────────────────────────────────┐
│ FeishuAPIClient │
│ - 认证管理 (tenant_access_token) │
│ - 统一请求封装 │
│ - 文件下载 │
└──────────────────────┬──────────────────────────────────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ WikiService │ │DocumentServ │ │MediaManager │
│ - 空间管理 │ │ - 文档内容 │ │ - 图片下载 │
│ - 节点遍历 │ │ - Block解析 │ │ - 文件下载 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼───────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ BlockToMarkdownConverter │
│ - Block类型转换 │
│ - 样式处理 │
│ - 媒体引用提取 │
└──────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ WikiExporter │
│ - 结构化导出 │
│ - 索引生成 │
│ - 元数据管理 │
└──────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Markdown Files + Assets │
│ (本地文件系统) │
└──────────────────────┬──────────────────────────────────┘
│
│ (可选) 同步
▼
┌─────────────────────────────────────────────────────────┐
│ Dify 知识库 │
└─────────────────────────────────────────────────────────┘
A: 可能是权限问题,确保应用有 drive:drive:readonly 权限,且图片在应用可访问的空间内。
A: 可以使用 --raw-content 参数使用更快的API,或增加 -c 并发数。但 raw_content 不支持所有块类型。
A: 使用 --parent-token 参数指定起始节点,只导出该节点下的子树。
A: 飞书复杂表格(合并单元格等)可能无法完美转换为Markdown表格,建议简化表格结构。
MIT License