创建飞书文档(Feishu DocX)。当用户说"写个飞书文档"、"创建飞书文档"、"生成飞书doc"、"feishu doc"等关键词时触发。
Scanned 9/13/2026
Install to Claude Code
npx -y skills add yangwhale/CloseCrab --skill feishu-doc --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Feishu Doc?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/yangwhale-feishu-doc)More formats (shields.io, HTML) on the badges page.
---
name: feishu-doc
description: 创建飞书文档(Feishu DocX)。当用户说"写个飞书文档"、"创建飞书文档"、"生成飞书doc"、"feishu doc"等关键词时触发。
license: MIT
---
# 飞书文档创建(Feishu DocX API)
通过飞书 DocX API 创建富格式文档,支持文本格式、标题、列表、表格、代码块、Callout、公式等全部原生能力。
## 触发条件
- "写个飞书文档"、"创建飞书文档"
- "生成飞书doc"、"feishu doc"
- "写到飞书文档里"、"输出成飞书文档"
## 前置条件
- 飞书 App 需要 `docx:document` 和 `drive:drive` 权限
- 环境变量已配置:`FEISHU_APP_ID_JARVIS` / `FEISHU_APP_SECRET_JARVIS`(或对应 bot 的 env)
## API 概览
### 1. 创建文档
```python
import os, lark_oapi as lark
from lark_oapi.api.docx.v1 import *
client = lark.Client.builder() \
.app_id(os.environ['FEISHU_APP_ID_JARVIS']) \
.app_secret(os.environ['FEISHU_APP_SECRET_JARVIS']) \
.domain(lark.FEISHU_DOMAIN).build()
req = CreateDocumentRequest.builder() \
.request_body(CreateDocumentRequestBody.builder()
.title("文档标题")
.folder_token("") # 空字符串 = 根目录
.build()).build()
resp = client.docx.v1.document.create(req)
doc_id = resp.data.document.document_id
```
### 2. 添加内容块
```python
body = CreateDocumentBlockChildrenRequestBody.builder() \
.children(blocks) # List[Block]
.index(-1) # -1 = 追加到末尾
.build()
req = CreateDocumentBlockChildrenRequest.builder() \
.document_id(doc_id) \
.block_id(parent_id) # doc_id = 根级,或容器 block_id
.document_revision_id(-1) # -1 = 最新版本
.request_body(body).build()
resp = client.docx.v1.document_block_children.create(req)
```
### 3. 获取子块(表格填充用)
```python
req = GetDocumentBlockChildrenRequest.builder() \
.document_id(doc_id) \
.block_id(table_block_id) \
.build()
resp = client.docx.v1.document_block_children.get(req)
cell_ids = [item.block_id for item in resp.data.items]
```
## Block Types 速查
| block_type | 类型 | Builder setter | 说明 |
|-----------|------|---------------|------|
| 2 | text | `.text()` | 普通文本段落 |
| 3-8 | heading1-6 | `.heading1()` ~ `.heading6()` | 标题 H1-H6 |
| 12 | bullet | `.bullet()` | 无序列表 |
| 13 | ordered | `.ordered()` | 有序列表 |
| 14 | code | `.code()` | 代码块 |
| 15 | quote | `.quote()` | 引用行 |
| 17 | todo | `.todo()` | 任务清单 |
| 19 | callout | `.callout()` | 高亮块(容器) |
| 22 | divider | `.divider({})` | 分割线 |
| 25 | grid | `.grid()` | 多列布局(API 不支持创建) |
| 27 | iframe | `.iframe()` | 内嵌网页 |
| 28 | image | `.image()` | 图片(需先上传获取 token) |
| 31 | table | `.table()` | 表格 |
| 34 | quote_container | `.quote_container({})` | 引用容器(可嵌套) |
## 构建 Block 的工具函数
以下函数可直接复制使用:
### make_text_element — 创建带格式的文本片段
```python
def make_text_element(content, bold=False, italic=False, underline=False,
strikethrough=False, inline_code=False,
text_color=None, bg_color=None, link=None):
style_builder = TextElementStyleBuilder()
if bold: style_builder.bold(True)
if italic: style_builder.italic(True)
if underline: style_builder.underline(True)
if strikethrough: style_builder.strikethrough(True)
if inline_code: style_builder.inline_code(True)
if text_color: style_builder.text_color(text_color) # 1=红 2=橙 3=黄 4=绿 5=蓝 6=紫
if bg_color: style_builder.background_color(bg_color) # 同上
if link: style_builder.link(LinkBuilder().url(link).build())
return TextElementBuilder() \
.text_run(TextRunBuilder().content(content)
.text_element_style(style_builder.build()).build()).build()
```
### make_text_block — 创建文本类 Block
```python
def make_text_block(elements, block_type=2, align=None, style_kwargs=None):
style_builder = TextStyleBuilder()
if align: style_builder.align(align) # 1=左 2=中 3=右
if style_kwargs:
if 'language' in style_kwargs: style_builder.language(style_kwargs['language'])
if 'done' in style_kwargs: style_builder.done(style_kwargs['done'])
text = TextBuilder().elements(elements).style(style_builder.build()).build()
bb = BlockBuilder().block_type(block_type)
type_map = {
2: 'text', 3: 'heading1', 4: 'heading2', 5: 'heading3',
6: 'heading4', 7: 'heading5', 8: 'heading6',
12: 'bullet', 13: 'ordered', 14: 'code', 15: 'quote', 17: 'todo',
}
getattr(bb, type_map.get(block_type, 'text'))(text)
return bb.build()
```
### make_divider — 分割线
```python
def make_divider():
return BlockBuilder().block_type(22).divider({}).build()
```
## 常用代码块语言 ID
| ID | 语言 | ID | 语言 |
|----|------|----|------|
| 1 | PlainText | 22 | JavaScript |
| 15 | Bash/Shell | 40 | TypeScript |
| 49 | Python | 18 | Java |
| 19 | JSON | 12 | Go |
| 7 | C++ | 56 | YAML |
| 29 | Markdown | 54 | SQL |
| 53 | Rust | 4 | C |
## Callout 高亮块
Callout 是容器块,创建后需要往内部添加子块:
```python
callout = BlockBuilder().block_type(19) \
.callout(CalloutBuilder()
.background_color(4) # 1=红 2=橙 3=黄 4=绿 5=蓝 6=紫
.border_color(4)
.emoji_id("bulb") # 英文 emoji 名称,非 unicode
.build()).build()
ids = add_blocks([callout])
add_blocks([make_text_block(...)], parent_id=ids[0]) # 填充内容
```
常用 emoji_id: `bulb`, `check`, `warning`, `star`, `crystal_ball`, `rocket`, `fire`, `heart`, `memo`, `pushpin`
## 表格
表格创建后自动生成空 cell,需要查询 cell_ids 再逐个填充:
```python
table = BlockBuilder().block_type(31) \
.table(TableBuilder()
.property(TablePropertyBuilder().row_size(3).column_size(4).build())
.cells([]).build()).build()
table_ids = add_blocks([table])
# 获取 cell block_ids
req = GetDocumentBlockChildrenRequest.builder() \
.document_id(doc_id).block_id(table_ids[0]).build()
resp = client.docx.v1.document_block_children.get(req)
cell_ids = [item.block_id for item in resp.data.items]
# cells 按行优先排列: [row0col0, row0col1, ..., row1col0, ...]
for idx, cell_id in enumerate(cell_ids):
row, col = idx // num_cols, idx % num_cols
add_blocks([make_text_block([make_text_element(data[row][col])])], parent_id=cell_id)
```
## 行内公式(LaTeX)
```python
make_text_block([
make_text_element("能量公式:"),
TextElementBuilder().equation(
EquationBuilder().content("E = mc^2").build()
).build(),
])
```
## 引用容器
容器块,可嵌套文本、列表等:
```python
qc = BlockBuilder().block_type(34).quote_container({}).build()
qc_ids = add_blocks([qc])
add_blocks([make_text_block(...)], parent_id=qc_ids[0])
```
## 图片
需要先上传文件获取 image token,再创建 image block:
```python
# 1. 上传图片到飞书(使用 drive API 的 upload_media)
# 2. 创建 image block
image_block = BlockBuilder().block_type(28) \
.image(ImageBuilder().token(image_token).width(800).height(400).build()).build()
```
## 注意事项
- **Rate limit**: 每秒约 5 次 API 调用,批量操作间加 `time.sleep(0.2)`
- **Grid 不支持 API 创建**: `block_type=25` 返回 `block not support to create`,只能在客户端手动添加
- **容器块填充**: Callout (19)、Quote Container (34)、Table Cell (32) 都是容器,创建后需要往 children 添加内容
- **document_revision_id=-1**: 总是使用最新版本,避免并发冲突
- **文档 URL**: `https://bytedance.feishu.cn/docx/{document_id}`
## 工作流程
1. **创建空文档** → 拿到 `document_id`
2. **规划内容结构** → 标题、段落、表格、Callout 等
3. **批量添加块** → 一次 API 调用可加多个同级 block
4. **填充容器** → 表格 cell、callout、quote_container 需要二次填充
5. **返回文档链接** → `https://bytedance.feishu.cn/docx/{document_id}`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!