ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用Obsidian和Python自动生成小说人物关系白板

用Obsidian和Python自动生成小说人物关系白板 写小说的人都有过这种体验写到第 20 章手里的角色超过 15 个读者已经开始追问“陈默到底和叶晚有什么仇”而你自己翻遍设定文档只记得“两人曾是同门”。更麻烦的是人物关系从来不是静态的——第一幕里是恩师第三幕里变成仇人第五幕又成了彼此的软肋。如果只靠脑内记忆和零散笔记写崩人物关系几乎是必然事件。本文要讲的就是怎么用 Obsidian 解决这个问题的把人物关系写成 Markdown 卡片然后用脚本一键生成一张可交互的人物关系白板不用手动拖拽不用反复改图。读完你会得到一套完整的、在本地运行的“人物关系可视化”工作流原理同样适用于剧本设定、知识管理和剧情线索整理。先说我的核心判断真正让效率提升的不是某个神奇插件而是“结构化写作 程序化生成”的组合。Obsidian 的 Canvas 白板看起来是一个手动工具但它的.canvas文件本质上是 JSON 格式这意味着我们完全可以让脚本把“人物关系笔记”自动翻译成“关系白板”。这篇文章会从痛点、原理、实现、验证到避坑完整走一遍。1. 为什么要给小说人物关系做可视化白板1.1 写小说的人真正缺的是一张动态关系图写长篇小说的瓶颈不是灵感而是“人物管理”。当角色只有 3 个时关系靠自己记没问题当角色超过 10 个关系线超过 20 条时光靠脑子已经不够用了。小说里的人物关系不只是“人物 A 认识人物 B”它往往包含多层语义两人是师徒、是恋人、是敌对的竞争对手甚至是背叛过后又和解的复杂关系。这些语义如果只存在于正文里检索非常困难。很多写作者会单独建一个“人物关系表”文档用列表或表格记录关系。这种做法的缺点是关系一旦变化你需要在文档里找到那个条目修改描述但小说更新到后期人物关系会经历多次反转手动维护的成本会快速上升。更麻烦的是文档里密密麻麻的文字列表根本没法让大脑快速形成全局图像。可视化白板解决的是“全局感知”问题。你打开一张画布一眼就能看出谁是核心人物谁和谁之间存在关键冲突哪个角色其实游离在主线之外。这种直觉判断对剧情推进非常重要。1.2 传统工具为什么不够用有人会用 Excel 做关系表也有人用在线脑图工具画关系图。但它们都有明显短板。先用一张表格对比常见方案方案直观性更新成本离线可用与写作笔记的耦合度Excel 表格低高支持几乎为零在线脑图工具中中部分支持低Obsidian 关系图谱中中支持高Obsidian Canvas 白板高手动调整较高支持高脚本生成 Canvas高低支持高Excel 的问题在于不直观。你能看到关系列表但很难在大脑中重建关系网络。在线脑图工具虽然直观但数据存在第三方服务器而且一旦你的写作场景切换到本地笔记脑图就变成了一个孤立的文件丧失了和人物小传、剧情大纲的上下文联系。最好的方案是让人物关系图直接长在笔记仓库里。人物卡的背景、性格、经历都在 Obsidian 中点击关系白板上的某个节点可以直接跳转到对应笔记——这正是 Obsidian 的强项。1.3 Obsidian 解决这个问题的核心路径Obsidian 提供了四个关键技术点让“自动生成人物关系白板”成为可能本地 Markdown 笔记数据完全掌握在自己手里。双链机制可以在人物笔记之间建立可追溯的语义关联。Canvas 白板提供可视化画布可以承载节点和连线。.canvas文件是 JSON 格式可以像普通文档一样被程序生成。把这四个点组合起来就得到本文的核心思路在人物笔记中写入结构化关系数据再用 Python 脚本读取这些数据生成一个.canvas文件最后在 Obsidian 中打开这个文件得到一张完整的人物关系白板。这篇文章不只是告诉你“可以这么做”而是直接给你可运行的脚本和完整示例复制过去就可以使用。2. 基础概念Markdown、双链、Graph View 与 Canvas2.1 概念速览在动手之前先把几个关键概念对齐。Markdown 是 Obsidian 的底层笔记格式。它用纯文本表达结构比如#代表标题-代表列表[[双链]]代表笔记之间的链接。所有内容都是普通文件不依赖专属数据库。双链是两篇笔记之间建立的链接关系。在 Obsidian 中输入[[张三]]就能创建一个指向“张三.md”的链接。双链的价值在于它让笔记不再是孤岛而是形成了可遍历的知识网络。Graph View 是 Obsidian 内置的关系图谱视图。它会根据笔记之间的双链关系把所有笔记渲染成一张大图可以直观看到哪些笔记处于核心位置。Canvas 是 Obsidian 的白板功能。它允许你在无限画布上摆放卡片、笔记、图片并用连线表达关系。和 Graph View 最大的区别是Graph View 是自动布局的Canvas 是手动布局的——但 Canvas 的文件是 JSON这给了程序化生成的窗口。2.2 为什么默认 Graph View 不够用Obsidian 的默认关系图谱很多人一开始觉得惊艳但真正用于小说人物管理时会发现它有两个明显问题。第一它只能告诉你“两篇笔记之间有链接”但无法告诉你“这是什么关系”。张三和李四之间有一条线这条线代表“师徒”还是“仇人”完全看不出来。第二Graph View 的布局是全局算法驱动的它不理解小说剧情的语义分组。你希望把“主角团队”和“反派阵营”分开显示但 Graph View 只会按连接密度进行聚合结果往往是一团乱麻。所以Graph View 适合做宏观概览不适合做精细的人物关系分析。这也是我们需要 Canvas 白板的原因——它允许我们自定义节点位置、连线颜色和标签把关系语义画出来。2.3 Canvas 白板的文件本质很多人不知道Obsidian 的.canvas文件本质上是一个 JSON 文件。它包含两类关键数据节点nodes和边edges。节点代表画布上的卡片每个节点有id、type、坐标和宽高。边代表卡片之间的连线每条边记录了fromNode、toNode、标签和颜色。因为格式是公开的 JSON所以我们完全可以用任何编程语言生成这个文件。脚本读入人物关系数据计算出节点坐标生成连线写入一个.canvas文件Obsidian 就能把它当作白板打开。这就是整个自动化方案的根基。3. 方案设计把“人物卡片”变成“程序能读的关系数据”3.1 人物卡片模板要让程序自动解析首先得让“人物”成为笔记中一种可识别的对象。我的做法是建立一个人物卡片目录每个角色放一个 Markdown 文件文件头部使用 YAML frontmatter 定义结构化字段。frontmatter 是 Markdown 文件开头的一段 YAML 元信息用两行---包裹。它非常适合存放人物属性因为 YAML 结构清晰程序可以直接读取。一个最小的人物卡片模板如下--- type: character name: 张三 tags: [小说, 主角] relations: - person: 李四 type: 师徒 direction: 单向 color: #ff9f43 - person: 王五 type: 敌对 direction: 双向 color: #e74c3c --- # 张三 ## 背景 此处写人物小传比如出身、经历、目标。 ## 性格 此处写性格分析比如优缺点、行为模式。这里type: character是关键标记用于让脚本识别“这是一个角色笔记”而不是普通笔记。relations字段定义了人物关系列表每个关系对象包含person、type、direction和color。3.2 用 frontmatter 存放关系的理由很多人会问为什么不用双链来记录关系双链当然有用它适合阅读和跳转。但如果把关系语义全部塞进双链脚本需要从正文文本中猜测人物之间的关系解析难度大且容易产生误判。比如“张三想到李四曾经教过他剑法”这句话用自然语言处理很难精确提取出“师徒”关系。frontmatter 的优势在于它是“程序友好的结构化数据”。字段边界明确含义清晰脚本读取几乎不会出错。同时frontmatter 里的person字段也可以写成[[李四]]的形式这样既保留了双链的跳转能力又让编程解析更精确。更稳妥的做法是双链和 frontmatter 配合使用正文中通过[[李四]]建立可追溯的关联frontmatter 中通过relations精确表达关系语义。前者给人看后者给程序读。3.3 关系语义设计type、direction、color在设计关系数据时有三个语义字段需要明确。type表示关系类型。常见的有师徒、敌对、恋人、家人、旧识、上下级等。建议你建立一个“关系类型字典”把关系类型统一收口避免出现“师父”和“师傅”、“敌人”和“仇人”混用的情况。direction表示关系方向取值为单向或双向。单向关系适合表达“暗恋”“单方面追查”这类语义双向关系适合表达“彼此信任”“互相仇恨”。Canvas 的原生连线对箭头的支持有限所以脚本会把方向信息拼进连线的标签里比如“师徒单向”。color表示关系连线颜色。用不同颜色区分关系类型可以大大提升白板的信息读取效率。比如红色代表敌对绿色代表盟友粉色代表恋人。3.4 为什么不用纯双链方案纯双链方案在 Obsidian 中可以直接生成 Graph View看起来似乎很省事。但它有两个致命问题。第一无法表达关系类型。双链只能表示“有关联”不能表示“是什么关联”。第二无法表达关系强度。两个人有 10 处互动应该比只有 1 处互动更紧密但纯双链图无法体现这种差异。所以我的结论是双链是重要的补充但不能作为唯一机制。人物关系自动化的核心还是前置的结构化关系数据。4. 环境准备与前置条件在动手之前先确认你的环境满足以下条件。4.1 软件环境需要准备一个 Obsidian 仓库并确认版本支持 Canvas 功能。Obsidian 从 1.1 版本开始内置 Canvas 核心插件建议使用较新的版本。如果你不确定自己的版本是否支持可以直接检查左侧边栏是否有 “Canvas” 核心插件如果没有在“设置 - 核心插件”中启用即可。脚本侧需要 Python 3.9 或以上版本。建议在命令行中执行python --version确认版本号。如果没有安装 Python请先安装并配置环境变量。还需要安装 PyYAML 库用于解析 Markdown 文件头部的 YAML frontmatter。安装命令如下pip install pyyaml如果你的网络环境使用镜像源可以手动指定源但这不是必须的正常安装即可。4.2 目录结构约定为了让脚本不至于把仓库里所有笔记都当成人物卡建议建立清晰的目录结构。我的建议如下你的 Obsidian 仓库/ ├── 00-收件箱/ ├── 10-设定集/ │ ├── 人物/ │ │ ├── 张三.md │ │ ├── 李四.md │ │ └── 王五.md │ ├── 势力/ │ └── 地点/ ├── 20-输出/ │ └── 人物关系图.canvas └── scripts/ └── generate_character_canvas.py10-设定集/人物目录专门存放人物卡片20-输出目录存放生成的 canvas 文件scripts目录存放脚本。目录命名可以按你的习惯调整但脚本里的路径要对应修改。4.3 前端文件准备如果你是第一次使用 YAML frontmatter建议先创建一个简单的人物卡片测试文件确认 Obsidian 能正常识别 frontmatter。Obsidian 在阅读视图下会把 frontmatter 区域渲染成属性面板如果你的版本不支持直接以源代码模式查看也是可以的。5. 核心流程拆解整个方案的实现流程可以拆成五步每个步骤都可以独立验证。5.1 建立人物仓库在 Obsidian 仓库中新建10-设定集/人物目录。为每一个重要角色创建一个 Markdown 文件文件名建议直接用角色名比如张三.md。文件名会成为最直观的标识也方便双链跳转。这一步的关键决策是所有人物卡片必须放在同一个目录下。这样脚本可以只扫描一个目录不需要全仓库递归遍历解析速度和准确性都有保障。5.2 为人物笔记写入关系数据以张三.md为例在文件头部写入 frontmatter--- type: character name: 张三 tags: [小说, 主角] relations: - person: 李四 type: 师徒 direction: 单向 color: #ff9f43 - person: 王五 type: 敌对 direction: 双向 color: #e74c3c - person: 赵六 type: 恋人 direction: 双向 color: #e84393 ---注意person字段的值要和其他人物笔记中的name字段严格一致。如果这里写“李四”但李四笔记里的name是“李四师父”脚本就无法匹配。建议name字段保持和文件名一致避免歧义。5.3 编写解析脚本脚本负责三件事读取指定目录下所有.md文件解析 frontmatter筛选出type: character的笔记从relations字段构建人物关系数据最终生成 canvas 文件。脚本的输入是人物笔记输出是.canvas文件。中间不需要任何人工干预这就是“一键生成”的含义。5.4 生成 canvas 文件脚本生成.canvas文件时需要为每个人物计算一个坐标位置。最简单可行的布局是网格布局每个人物占一个网格从左到右依次排列超过每行数量后换行。虽然这种布局不如力导向图美观但胜在逻辑清晰而且生成后可以在 Obsidian 中手动微调。5.5 在 Obsidian 中打开白板脚本运行结束后回到 Obsidian 仓库打开20-输出/人物关系图.canvas。Obsidian 会把 canvas 文件渲染成白板画布人物节点和关系连线会出现在画布上。你可以在白板中拖动节点调整布局也可以点击节点跳转到对应的人物笔记。如果 Obsidian 已经处于打开状态生成新文件后通常需要等待几秒让文件系统刷新或者直接关闭重新打开文件。6. 完整示例代码实现下面的代码是完整可运行的示例。你只需要把路径改成自己仓库的路径即可。6.1 脚本文件创建scripts/generate_character_canvas.py完整代码如下 生成人物关系白板脚本 功能扫描 Obsidian 仓库中的人物卡片解析 frontmatter 关系数据 生成一个可被 Obsidian 打开的 .canvas 文件。 import json import re from pathlib import Path import yaml # 配置区按你的 Obsidian 仓库实际情况修改 VAULT_DIR Path(D:/ObsidianVault) # Obsidian 仓库根目录 CHARACTER_DIR VAULT_DIR / 10-设定集/人物 # 人物卡片所在目录 OUTPUT_FILE VAULT_DIR / 20-输出/人物关系图.canvas # 输出 canvas 文件 # 画布布局参数 NODE_WIDTH 240 NODE_HEIGHT 140 HORIZONTAL_SPACING 80 VERTICAL_SPACING 60 COLUMNS 4 def read_frontmatter(md_path: Path): 读取 Markdown 文件顶部的 YAML frontmatter text md_path.read_text(encodingutf-8) match re.match(r^---\s*\n(.*?)\n---, text, re.DOTALL) if not match: return None try: return yaml.safe_load(match.group(1)) except yaml.YAMLError as e: print(f解析失败{md_path.name}错误{e}) return None def build_nodes(characters): 根据人物列表生成 canvas 节点 nodes [] for i, character in enumerate(characters): col i % COLUMNS row i // COLUMNS x col * (NODE_WIDTH HORIZONTAL_SPACING) y row * (NODE_HEIGHT VERTICAL_SPACING) nodes.append({ id: fchar-{i 1}, type: text, text: character[name], x: x, y: y, width: NODE_WIDTH, height: NODE_HEIGHT, }) return nodes def build_edges(characters): 根据人物关系生成 canvas 连线 edges [] edge_id 1 for i, character in enumerate(characters): for relation in character.get(relations, []): target_name relation.get(person, ) # 在人物列表中查找目标人物 target_index next( (idx for idx, c in enumerate(characters) if c[name] target_name), None, ) if target_index is None: print(f警告{character[name]} 的关系对象 {target_name} 不存在) continue # 拼接方向信息到标签中 label relation.get(type, ) direction relation.get(direction, ) if direction: label f{label}{direction} edges.append({ id: fedge-{edge_id}, fromNode: fchar-{i 1}, toNode: fchar-{target_index 1}, fromSide: right, toSide: left, label: label, color: relation.get(color, #999999), }) edge_id 1 return edges def main(): characters [] if not CHARACTER_DIR.exists(): print(f人物目录不存在{CHARACTER_DIR}) return for md_file in sorted(CHARACTER_DIR.glob(*.md)): frontmatter read_frontmatter(md_file) if not frontmatter: continue if frontmatter.get(type) ! character: continue characters.append({ name: frontmatter.get(name, md_file.stem), relations: frontmatter.get(relations, []), }) if not characters: print(未找到任何人物卡片请检查目录和 frontmatter 配置) return canvas_data { nodes: build_nodes(characters), edges: build_edges(characters), } OUTPUT_FILE.parent.mkdir(parentsTrue, exist_okTrue) OUTPUT_FILE.write_text( json.dumps(canvas_data, ensure_asciiFalse, indent2), encodingutf-8, ) print(f生成成功{OUTPUT_FILE}) print(f共 {len(characters)} 个人物{len(canvas_data[edges])} 条关系) if __name__ __main__: main()这个脚本的关键逻辑有三处第一read_frontmatter函数用正则提取笔记开头两个---之间的内容再用 PyYAML 解析。如果笔记没有 frontmatter返回 None脚本会自动跳过——这样普通笔记不会干扰人物关系图。第二build_edges函数在生成连线时会先根据person字段查找目标人物。如果目录里没有对应人物脚本会打印警告但不会崩溃。这样即使你漏建了某个人物卡片也能正常生成其他关系。第三输出文件采用json.dumps写入ensure_asciiFalse确保中文正常显示indent2让文件可读方便手动检查。6.2 示例人物笔记在10-设定集/人物目录下创建三个人物卡片。张三.md--- type: character name: 张三 tags: [小说, 主角] relations: - person: 李四 type: 师徒 direction: 单向 color: #ff9f43 - person: 王五 type: 敌对 direction: 双向 color: #e74c3c --- # 张三 ## 背景 张三出身平凡但因一次意外踏入修行界从此卷入各方势力争斗。 ## 性格 谨慎、重情义但在关键时刻敢于冒险。李四.md--- type: character name: 李四 tags: [小说, 师父] relations: - person: 张三 type: 师徒 direction: 单向 color: #ff9f43 - person: 王五 type: 旧识 direction: 双向 color: #10ac84 --- # 李四 ## 背景 李四是修行界的老前辈曾收张三为徒授其剑法。 ## 性格 外冷内热对徒弟保护欲极强。王五.md--- type: character name: 王五 tags: [小说, 反派] relations: - person: 张三 type: 敌对 direction: 双向 color: #e74c3c --- # 王五 ## 背景 王五是反派势力核心人物与张三立场完全对立。 ## 性格 野心勃勃行事果断不相信任何人。这三个人物之间形成了三条关系张三和李四的师徒关系、张三和王五的敌对关系、李四和王五的旧识关系。运行脚本后画布上应该出现三个节点和三条连线。6.3 生成的 Canvas 文件示例脚本运行后20-输出/人物关系图.canvas的内容大致如下{ nodes: [ { id: char-1, type: text, text: 张三, x: 0, y: 0, width: 240, height: 140 }, { id: char-2, type: text, text: 李四, x: 320, y: 0, width: 240, height: 140 }, { id: char-3, type: text, text: 王五, x: 640, y: 0, width: 240, height: 140 } ], edges: [ { id: edge-1, fromNode: char-1, toNode: char-2, fromSide: right, toSide: left, label: 师徒单向, color: #ff9f43 }, { id: edge-2, fromNode: char-1, toNode: char-3, fromSide: right, toSide: left, label: 敌对双向, color: #e74c3c }, { id: edge-3, fromNode: char-2, toNode: char-3, fromSide: right, toSide: left, label: 旧识双向, color: #10ac84 } ] }Obsidian 打开这个文件时会自动解析 JSON渲染成可视化画布。每个人物是一个卡片卡片之间带标签的线代表关系颜色区分关系类型。7. 运行结果与效果验证7.1 运行命令切换到脚本所在目录执行cd D:/ObsidianVault/scripts python generate_character_canvas.py如果一切正常控制台会输出类似信息生成成功D:\ObsidianVault\20-输出\人物关系图.canvas 共 3 个人物3 条关系这说明脚本找到 3 个人物卡片生成了 3 条关系连线。7.2 在 Obsidian 中打开白板回到 Obsidian点击20-输出目录下的人物关系图.canvas文件。Obsidian 会切换到白板视图三个卡片排列在画布上三条连线带着标签显示出来。验证成功的标准有三个三个卡片都显示对应人物名称。卡片之间出现连线连线上显示“师徒单向”“敌对双向”等标签。颜色符合 frontmatter 中的配置。如果只有一个卡片出现说明其他笔记没有被解析到优先检查type: character字段是否写对。7.3 失败排查第一步如果脚本输出“未找到任何人物卡片”第一步不是改代码而是检查CHARACTER_DIR路径是否正确。Windows 路径容易出问题建议在脚本里加一行打印print(f当前扫描目录{CHARACTER_DIR})确认目录存在且包含.md文件后再检查 frontmatter 格式。很多人会把 frontmatter 写成这样--- type: character name: 张三 relations: [] ---这是合法的但如果缺少type: character脚本会直接跳过。8. 常见问题与排查思路下面这张表汇总了最容易踩的几个坑按出现频率排序。问题现象可能原因排查方式解决方案脚本提示“未找到任何人物卡片”人物目录路径错误或 frontmatter 缺少 type 字段打印扫描目录检查人物卡片是否在正确目录下修正CHARACTER_DIR路径或为笔记补上type: character生成的白板中某个卡片缺失该笔记的 frontmatter 无法解析或 name 字段为空用文本编辑器打开笔记检查 frontmatter 是否完整修正 YAML 格式确保name字段存在关系线没有出现两个人物的name与person字段不匹配控制台会打印警告查看具体是哪个关系对象找不到统一name和person的命名建议保持一致中文乱码Windows 控制台默认编码问题查看控制台输出是否出现乱码执行时加上PYTHONIOENCODINGutf-8Canvas 打开后颜色不生效颜色值格式不被 Obsidian 识别打开 Obsidian 自带的 canvas 文件对比颜色字段格式改用内置色号或标准 hex 颜色运行时提示 module yaml 不存在PyYAML 未安装执行pip show pyyaml查看执行pip install pyyaml有一个比较容易忽略的点Obsidian 对.canvas文件的识别依赖nodes和edges字段的 JSON 格式。如果你手动调整过脚本生成的文件缺少edges字段Obsidian 可能只显示卡片不显示连线。请保持脚本中两个字段都存在。另外不要在生成 canvas 文件时用json.dumps的默认ensure_asciiTrue否则 JSON 里会出现\uXXXX转义虽然 Obsidian 也能读但可读性会变差。9. 最佳实践与工程建议9.1 统一人物命名规范人物命名是关系匹配的基础。建议所有人物笔记的文件名、name字段、关系中的person字段都保持完全一致。不要出现“张三”和“张三少年期”混用的情况。如果同一个角色在不同时期性格差异很大可以在人物笔记内部用不同小节描述而不是拆成多个笔记。关系数据中人物始终对应一个唯一标识。9.2 建立关系类型字典随着人物数量增加关系类型会越来越多。如果不做收口很快会出现“师父”“师尊”“师傅”三种写法。建议在设定集里维护一个“关系类型字典”明确每种关系的标准写法和颜色。示例关系类型字典: 师徒: #ff9f43 敌对: #e74c3c 恋人: #e84393 家人: #6c5ce7 旧识: #10ac84 上下级: #0984e3 盟友: #00b894脚本设计时可以先查字典获取颜色而不是每一条关系都手动写 color。这样统一管理和后期调整都更高效。9.3 把脚本变成“一键”操作现在脚本需要手动执行python generate_character_canvas.py。如果你想真正做到“一键”有两种方式。第一种使用 Obsidian 的 Templater 插件配合一个自定义命令调用外部脚本。Templater 可以触发系统命令绑定快捷键后在 Obsidian 里按快捷键就能生成白板。第二种直接把 Python 脚本封装成 Obsidian 插件。Obsidian 插件基于 JavaScript你可以用 Node.js 实现同样的解析逻辑然后注册进 Obsidian 的命令面板。这个方案的优点是无需离开 Obsidian缺点是开发成本稍高。如果你熟悉 JavaScript值得尝试如果只想快速落地先用 Python 脚本即可。9.4 善用 Graph View 补充视角Canvas 生成的是“当前人物关系快照”Graph View 则提供整个仓库的全局视角。二者可以结合使用Graph View 用来快速发现哪些人物笔记还没有建立双链Canvas 用来展示精心整理过的人物关系白板。建议在人物卡片正文中写上完整的[[双链]]这样 Graph View 中也能看到人物与势力、地点、事件之间的关系。双链负责“可追溯性”frontmatter 负责“可计算性”两者各司其职。9.5 周期性清理失效关系小说中期改设定很常见。人物关系变化后不要只改正文也要同步更新 frontmatter 中的relations字段。否则脚本生成的白板上会出现过时的“旧关系”误导你的创作判断。最简单的做法是每次大改设定后重新运行一次脚本生成全新的 canvas 文件。脚本会把旧文件覆盖所以不存在数据冗余问题。10. 总结与后续扩展本文从写小说人物管理的实际痛点出发讲清楚了 Obsidian 中“人物关系白板自动化”的完整路径用 Markdown 卡片保存人物信息用 YAML frontmatter 存关系数据用 Python 脚本解析数据并生成.canvas文件最后在 Obsidian 中打开查看。这套方案真正的价值不是替代你手动创建白板而是让白板内容始终和笔记数据保持同步。你只需要维护人物卡片的 frontmatter脚本会自动帮你把关系网络画出来。人物多了、关系改变了重新运行一次脚本即可得到最新的白板。如果你已经跑通了这个脚本下一步可以往两个方向深入。一个方向是扩展关系类型不止人物关系还可以为势力、组织、地点建立同样的“卡片 frontmatter 脚本生成”模式另一个方向是把脚本升级为 Obsidian 插件用 JavaScript 重写解析逻辑把整个流程完全嵌进 Obsidian 的命令面板。这两条路都能进一步提升效率但前提是你先掌握今天这套“结构化写作 程序化生成”的核心思路。建议你从三个人物卡片的例子开始跑通确认 Obsidian 能正常打开生成的 canvas 文件再逐步把真实的人物库迁移进来。先跑通再优化这是最稳妥的做法。
返回列表