🐍 trilium-py
May 26, 2026 · View on GitHub
English | 简体中文
Important
中文文档可能落后于英文文档,如果有问题请先查看英文文档。
Trilium Note 的 ETAPI 和 Web API 的 Python 客户端,并提供额外的高级功能。
🦮 目录
- 🐍 trilium-py
- 💰 捐赠
- 🙏 感谢
🔧 安装
python3 -m pip install trilium-py --user
🚀 初始化
ETAPI 初始化
如果你有一个ETAPI令牌,请将 server_url 和 token 更改为你自己的。
from trilium_py.client import ETAPI
server_url = 'http://localhost:8080'
token = 'YOUR_TOKEN'
ea = ETAPI(server_url, token)
如果你还没有创建ETAPI令牌,你可以使用密码创建一个。请注意,你只能看到这个令牌一次,请保存它以便重用。
from trilium_py.client import ETAPI
server_url = 'http://localhost:8080'
password = '1234'
ea = ETAPI(server_url)
token = ea.login(password)
print(token)
初始化后,就可以使用Python使用Trilium的 ETAPI 了。
Web API 初始化
由于 CSRF 限制,每次使用 Web API 时都需要登录。
from trilium_py.src.trilium_py.web_client import WEBAPI
server_url = 'http://localhost:8080'
password = '1234'
wa = WEBAPI(server_url)
wa.login(password)
初始化后,就可以使用Python使用Trilium的 Web API 了。
📖 (基本) ETAPI 用法
以下是Trilium的ETAPI提供的基本功能。下面是一些使用这个包的简单示例代码。
📊 应用信息
首先,你可以获取应用程序的信息。
print(ea.app_info())
可以输出服务器应用程序的版本等信息。
🔍 搜索笔记
使用关键字搜索笔记。
res = ea.search_note(
search="python",
)
for x in res['results']:
print(x['noteId'], x['title'])
使用正则表达式进行搜索。例如,搜索并获取特定笔记下的所有子笔记:
res = ea.search_note(
# 通过笔记标题进行正则表达式搜索
search="note.title %= '.*'",
ancestorNoteId="父笔记ID",
fastSearch=False,
orderBy=["title"],
limit=100,
)
注意: limit 必须配合 orderBy 一起使用
🏭 创建笔记
你可以像这样创建一个简单的笔记。
res = ea.create_note(
parentNoteId="root",
title="笔记标题",
type="text",
content="笔记内容",
noteId="note1"
)
noteId 不是必需的,如果没有提供,Trilium会生成一个随机的。返回信息里可以看到这个noteId的值。
noteId = res['note']['noteId']
🖼️ 创建图片笔记
图像笔记是一种特殊类型的笔记。你可以使用最少的信息创建一个图像笔记,如下所示。image_file 是图片的路径。
res = ea.create_image_note(
parentNoteId="root",
title="Image note 1",
image_file="shield.png",
)
👀 获取笔记
检索笔记的内容。
ea.get_note_content("noteid")
你可以通过笔记的ID获取笔记的元数据。
ea.get_note(note_id)
🔄 更新笔记
更新笔记内容
ea.update_note_content("noteid", "由Python更新")
修改笔记标题
ea.patch_note(
noteId="noteid",
title="Python客户端修改",
)
🗑️ 删除笔记
通过笔记ID删除一个笔记。
ea.delete_note("noteid")
📄 创建笔记克隆(分支)
在 ETAPI 中,这个对象被称为 branch(分支),但在 Trilium 的用户界面中,它实际上表示的是一个 笔记克隆(note clone)。
下面的示例演示如何在 note1 下创建 note2 的一个克隆:
res = ea.create_branch(
noteId="note2",
parentNoteId="note1",
)
返回的结果示例如下:
{
'branchId': 'note1_note2',
'noteId': 'note2',
'parentNoteId': 'note1',
'prefix': None,
'notePosition': 10,
'isExpanded': False,
'utcDateModified': '2025-10-21T03:25:16.397Z'
}
💡 提示: 在 Trilium 的数据模型中,branch(分支) 是 clone(克隆) 的内部表示形式。 删除分支只会移除该父子关系链接,而不会删除实际的笔记。
🔍 获取笔记克隆信息
通过 branchId 获取指定笔记克隆(分支)的详细信息:
res = ea.get_branch(branchId="note1_note2")
✏️ 修改笔记克隆信息
更新现有笔记克隆的显示属性,例如前缀、顺序或展开状态:
res = ea.patch_branch(
branchId="note1_note2",
notePosition=0,
prefix="patched",
isExpanded=False
)
❌ 删除笔记克隆
从树结构中移除一个笔记克隆(分支)。 这只会断开与父笔记的链接,不会删除笔记本身:
res = ea.delete_branch(branchId="note1_note2")
📅 日记
你可以使用 get_day_note 获取特定日期的内容。日期字符串应该采用"%Y-%m-%d"的格式,例如 "2022-02-25"。
ea.get_day_note("2022-02-25")
然后使用 set_day_note 设置/更新一个日记。内容应该是一个(HTML)字符串。
ea.set_day_note(date, new_content)
📤 导出笔记
导出笔记有两种格式 html 或 markdown/md。将 noteId 设置为 root 可以导出所有笔记。
res = ea.export_note(
noteId='sK5fn4T6yZRI',
format='md',
savePath='/home/nate/data/1/test.zip',
)
💾 创建数据备份
这个例子将创建一个数据库备份文件,类似于 trilium-data/backup/backup-test.db。
res = ea.backup("test")
你可以使用Linux中的cron实用程序来安排定期自动备份。例如,要在每天上午3:00进行一次备份,你可以使用以下cron表达式:
0 3 * * * python /path/to/backup-script.py
获取附件信息
获取图片标题等。
res = ea.get_attachment('Y5V6pYq6nwXo')
更新附件信息
更改图片标题等。
res = ea.update_attachment(
attachmentId='2b7pPzqocS1s', title='你好ETAPI', role='image', mime='image/png'
)
获取附件内容
获取真实的图片文件。
res = ea.get_attachment_content('icpDE4orQxlI')
with open('1.png', 'wb') as f:
f.write(res)
更新附件内容
用新的图片替换旧的。
res = ea.update_attachment_content('icWqV6zFtE0V', '/home/nate/data/1.png')
创建附件
上传一个图片文件作为笔记的附件。
res = ea.create_attachment(
ownerId='8m8luXym5LxT',
file_path='/home/nate/data/ksnip_20230630-103509.png',
)
(高级用法) ✅ TODO 列表
借助Python的强大功能,我已经扩展了ETAPI的基本用法。现在你可以对待办事项列表做一些事情了。
添加TODO项
你可以使用 add_todo 来添加一个TODO项,参数是TODO的描述。
ea.add_todo("买暖宝宝")
检查/取消检查TODO项
参数是TODO项的索引。
ea.todo_check(0)
ea.todo_uncheck(1)
更新TODO项
使用 update_todo 来更新某个索引处的TODO项描述。
ea.update_todo(0, "去码头整点薯条")
删除TODO项
通过索引删除TODO项。
ea.delete_todo(1)
将昨天未完成的待办事项移到今天
如标题所示,你可以将昨天未完成的事情移到今天。未完成的待办事项将从昨天的笔记中删除。
ea.move_yesterday_unfinished_todo_to_today()
整理待办事项 (Sort todo)
整理今天的待办事项,将已完成的排在后面,并保持原有相对顺序
ea.sort_todo()
整理指定日期的待办事项
ea.sort_todo(date="2026-05-26")
整理并将新完成的待办事项追加到最下方
ea.sort_todo(append_new_done=True)
整理指定笔记id的待办事项
ea.sort_todo(noteId="fn1DVZBsiQBG")
(高级用法) 🚚 上传Markdown文件
上传单个带图片的Markdown文件
现在你可以将带有图片的Markdown文件导入Trilium了!trilium-py将帮助你上传图片并为你修复链接!
res = ea.upload_md_file(
parentNoteId="root",
file="./md-demo/manjaro 修改caps lock.md",
)
禁用数学公式解析
当上传包含美元符号($)的Markdown文件,但这些美元符号并非用于数学公式时,可以禁用数学公式解析:
res = ea.upload_md_file(
parentNoteId="root",
file="./md-demo/包含美元符号的文档.md",
parse_math=False, # 禁用数学公式解析
)
批量上传文件夹中的Markdown文件
你可以上传一个包含许多Markdown文件的文件夹到Trilium并保留文件夹结构!
从VNote导入
比如,上传所有来自VNote的笔记,只需执行以下操作:
res = ea.upload_md_folder(
parentNoteId="root",
mdFolder="~/data/vnotebook/",
ignoreFolder=['vx_notebook', 'vx_recycle_bin', 'vx_images', '_v_images'],
)
从Joplin导入
Joplin可以轻松导入。
res = ea.upload_md_folder(
parentNoteId="root",
mdFolder="/home/nate/data/joplin_data/",
ignoreFolder=['_resources', ],
)
从Logseq导入
res = ea.upload_md_folder(
parentNoteId="root",
mdFolder="/home/nate/data/logseq_data/",
ignoreFolder=['assets', 'logseq'],
)
从Obsidian导入
Obsidian有一个非常独特的文件链接系统。你应该使用obsidian-export将Obsidian vault转换为常规的Markdown文件。然后再使用trilium-py将笔记导入Trilium。
首先进行转换。
obsidian-export /path/to/your/vault /out
然后像导入普通markdown一样导入,trilium-py会为你处理图片。
res = ea.upload_md_folder(
parentNoteId="root",
mdFolder="E:/data/out",
)
从有道云笔记导入
有道云笔记不再提供导出功能。不过好在你可以使用https://github.com/DeppWang/youdaonote-pull 下载你的笔记并将其转换为Markdown文件。之后,trilium-py应该能够帮助你导入它们。
res = ea.upload_md_folder(
parentNoteId="root",
mdFolder="/home/nate/gitRepo/youdaonote-pull/out/",
)
从Turtl导入
你需要首先将Turtl从json转换为markdown。 详见 turtl-to-markdown。
然后你可以像这样使用trilium-py导入:
res = ea.upload_md_folder(
parentNoteId="root",
mdFolder="/home/nate/gitRepo/turtl-to-markdown/out/",
ignoreFolder=['_resources'],
)
从其他Markdown软件导入
一般来说,markdown文件有各种标准。你可以尝试使用以下方法导入它们
res = ea.upload_md_folder(
parentNoteId="root",
mdFolder="/home/nate/data/your_markdown_files/",
)
如果有任何问题,请随时创建一个issue。
批量导入时禁用数学公式解析
同样,在批量导入Markdown文件时也可以禁用数学公式解析:
res = ea.upload_md_folder(
parentNoteId="root",
mdFolder="~/data/财务文档/",
parse_math=False, # 禁用文件夹中所有文件的数学公式解析
)
(高级用法) 🎨 美化笔记
由于Trilium使用的库的限制,导入的笔记可能会遇到轻微的格式问题。这些问题包括代码块末尾出现额外的一行,图像与笔记内容融为一体,标题之间缺少换行符,导致笔记内容显得拥挤。
在日常整理资料时,一些从 网上复制的文字、通过 剪藏插件保存的页面,或者从 其他软件导入的笔记 ,经常会带有冗余的空行、不统一的标题层级、奇怪的排版等问题,看起来比较杂乱。
美化笔记可以自动清理这些冗余内容,并规范化标题和段落排版,让笔记更简洁、清晰、易于阅读。

以下是你可以用来美化你的笔记的方法。
美化笔记
指定笔记ID以美化笔记内容。
ea.beautify_note('krm8B9JthNfi')
美化笔记及其子笔记
ea.beautify_sub_notes('tlPuzU2szLJh')
(高级用法) 🧹 排序笔记内容
按照标题名称对笔记进行排序。这个功能对包含大量列表的笔记非常有价值,比如按各种流派排序的书名列表。它同样适用于管理浏览器书签或收集链接。
此外,你还可以为排序指定一个语言代码,以根据你的本地语言进行排序。这可以增强排序过程并使其适应你的语言偏好。
res = ea.sort_note_content('lPxtkknjR2bJ')
res = ea.sort_note_content('y6hROhWjNmHQ', 'zh_CN.UTF-8')
##(高级用法)🧹 删除空的“新笔记”
有时,我无意中创建了大量的“新笔记”,而这些笔记在我的笔记树中仍未被删除。这些“新笔记”使我的工作区杂乱不堪,散落在各个地方。我开发了这个批量删除空的“新笔记”的功能。此外,它会为包含内容的“新笔记”生成警告消息,也许我们应该为这些笔记更改标题。
ea.delete_empty_note()
(高级用法)🗜️ 优化图片大小
尝试使用PIL的优化功能来减少图片大小。如果你笔记中的图片没有压缩过,可以试试这个方法。 在执行这个过程后,我成功地将一个44MB的笔记转换为9.9MB。尝试之前请备份数据。
默认质量设置为90。
optimize_image_attachments 会保留原始图像格式并尝试压缩它。
ea.optimize_image_attachments('uMJt0Ajr1CuC')
为了进一步节省空间,可以尝试以下方法。
optimize_image_attachments_to_webp 函数将图像转换为 WebP 格式,显著减少文件大小。根据我的经验,WebP 图像的大小可能只有
PNG 图像的25%到50%。
ea.optimize_image_attachments_to_webp('H2q3901uFDCH')
如果你有很多剪辑的页面,这个操作可以节省大量空间。发明 WebP 的人真是个天才。
(高级用法)🔗 自动添加内部链接
此功能可以在笔记中自动创建内部链接。以下是使用示例:
示例
这是一个示例笔记:

执行以下代码后:
auto_create_internal_link('put_note_id_here')
笔记变成这样:

可以看到,部分文本已被替换为内部链接。该功能遵循以下规则:
- 标题匹配:与其他笔记标题匹配的内容会被替换为内部链接。
- 重复标题忽略:如果存在多个笔记使用相同标题,则不会为该标题创建链接。
- 优先匹配较长标题:较长的标题优先。例如,在上面的示例中,
Nate River被链接,而不是River。 - 现有链接保留:文本中已有的链接不会被修改。
然而,在示例中,像 "make" 和 "work" 这样的词属于我的笔记《我不认识的英语单词》。由于这些词短且常用,我不希望它们频繁生成内部链接。
排除特定笔记的内部链接
如果需要排除某些笔记的链接:
- 给这些笔记添加标签
#ignoreAutoInternalLink,这些笔记(及其子笔记)将在创建内部链接时被忽略。 - 你可以设置为可继承的:为父笔记添加这个标签并设置为可继承的,其所有子笔记也会被自动排除。
应用排除规则后,效果如下:

结果更加简洁美观。
特殊情况:重复标题
当多个笔记共享相同标题时,以下情况可以生成内部链接:
- 直接子笔记优先:直接子笔记的优先级高于其他拥有相同标题的笔记。
例如:

在此例中,笔记 TriliumNext 会将 "How to compile" 链接到自己的子笔记,而不是 Trilium 的同名笔记。
最后一条规则:避免自引用
笔记不会创建指向自身的内部链接。
代码示例
为特定笔记添加内部链接(通过笔记 ID):
auto_create_internal_link('gLmmsIM8yPqx')
为多个笔记添加内部链接:
auto_create_internal_link(target_notes=['gLmmsIM8yPqx', 'T4Ui3wNByO03'])
(实验性功能 - 谨慎使用) 为所有文本笔记添加内部链接:
这是一个实验性功能。在使用前请备份数据库,因为此操作可能会不可逆地修改您的笔记。如果使用后发现问题,请提供一个最小化的笔记样本以便调试。
auto_create_internal_link(process_all_notes=True)
##(高级用法)📝🌳 遍历笔记树
获取某个笔记的标题和内容,以及其所有子笔记的标题和内容。非常适用于重新组合拆分成较小子笔记的大型笔记。
方法可以是 bfs(广度优先搜索)或 dfs(深度优先搜索)。
res = ea.traverse_note_tree('XdOlGz7MeYWC', depth=3, limit=100, method='bfs')
for x in res:
logger.info(x)
(高级用法) 🗓️🔁 周期性 TODO
你可以使用 add_periodic_todos 来自动添加周期性任务(每天、每周、每月、每年)。 如果某个任务在今天到期,并且今天的 TODO 里还没有,就会自动添加进去。
periodic_todos = [
# 每天伸展身体
{"content": "伸展身体", "type": "daily"},
# 每天给 Nriver 买牛奶 :)
{"content": "给 Nriver 买牛奶 :)", "type": "daily"},
# 每周六洗衣服
{"content": "洗衣服", "type": "weekly", "weekday": 6},
# 每月 1 号写总结报告
{"content": "写总结报告", "type": "monthly", "day": 1},
# 每月最后一天交房租
{"content": "交房租", "type": "monthly", "day": -1},
# 每月 10 号买抗过敏药
{"content": "买抗过敏药", "type": "monthly", "day": 10},
# 每年 12 月 31 日年度总结
{"content": "年度总结", "type": "yearly", "month": 12, "day": 31},
# 每年 1 月 1 日新年快乐 :)
{"content": "新年快乐 :)", "type": "yearly", "month": 1, "day": 1},
# 每月 15 号缴账单,直到 2077-01-01
{"content": "缴账单", "type": "monthly", "day": 15, "end_date": "2077-01-01"},
# 从 2025-01-01 开始,每周一团队会议
{"content": "团队会议", "type": "weekly", "weekday": 1, "start_date": "2025-01-01"},
# 2025-09-26 到 2025-09-30 的特别项目
{"content": "特别项目", "type": "daily", "start_date": "2025-09-26", "end_date": "2025-09-30"},
]
res = ea.add_periodic_todos(periodic_todos)
(基础) Web API 使用
这些功能是基于 Trilium Web 客户端的 Web API 开发的。在使用之前,请确保已完成初始化。
📄 获取笔记内容
通过笔记 ID 轻松获取笔记内容。
res = wa.get_note_content('RfhYrtyQLU8o')
🔒 受保护的会话 / 加密的笔记
使用 enter_protected_session 方法进入保护会话。 进入保护会话后,即可访问被加密保护的笔记。
wa.enter_protected_session(password)
res = wa.get_note_content(protected_note_id)
使用 leave_protected_session 方法退出保护会话。
wa.leave_protected_session()
🔄 更新笔记内容
传入笔记id和内容即可. 如果是受保护的笔记,请先进入受保护的会话。
wa.update_note_content(note_id, '<p>protected note content updated by trilium-py :)</p>')
📣 分享笔记 & 取消分享笔记
wa.share_note('你的笔记ID')
wa.cancel_share_note('RfhYrtyQLU8o')
🛠️ 开发
使用pip egg link进行安装,以便在不重新安装的情况下进行包更改。
python -m pip install --user -e .
🔗 原始OpenAPI文档
原始OpenAPI文档在这里 。你可以使用swagger editor打开它。
💰 捐赠
如果你喜欢使用 Trilium-py,欢迎支持我的开发工作!
支付宝

微信支付

🙏 感谢
感谢 Matt Wilkie 赞助的 10.0 美元!