首页
/ 3个隐秘技巧,让Trilium Notes成为你的第二大脑

3个隐秘技巧,让Trilium Notes成为你的第二大脑

2026-04-04 09:21:01作者:裘晴惠Vivianne

你是否曾在整理大量笔记时感到无从下手?当知识积累到一定程度,如何让分散的笔记自动关联,形成结构化的知识网络? Trilium Notes(以下简称Trilium)的脚本编程功能就像一把瑞士军刀,能将你的笔记系统从简单的存储工具升级为智能知识助手。本文将通过三个实用案例,带你掌握Trilium自动化的核心方法,让知识管理从被动整理变为主动生长。

核心能力解析:Trilium脚本引擎

Trilium提供两套强大的脚本API,就像为知识管理配备了"左右脑"。后端API负责数据处理和逻辑运算,如同"左脑"般严谨高效;前端API专注用户交互和界面扩展,如同"右脑"般灵活直观。

后端脚本:数据操作的核心引擎

后端脚本运行在Trilium服务端,拥有数据库操作权限,适合处理批量数据任务。其核心入口位于src/services/backend_script_api.js,提供三类关键能力:

  • 笔记操作:创建、查询、更新和删除笔记及属性
  • 事务处理:确保批量操作的原子性,避免数据不一致
  • 搜索功能:使用Trilium强大的查询语法筛选内容
// 后端脚本基础示例
// 创建带标签的笔记
const {note} = api.createTextNote(
  "parent-note-id",  // 父笔记ID
  "新知识笔记",      // 标题
  "笔记内容"         // 内容
);

// 添加标签属性
note.setLabel("type", "article");
note.save();

// 事务处理示例
api.transactional(() => {
  // 批量操作代码
  // [!TIP] 事务确保所有操作要么全部成功,要么全部失败
});

前端脚本:交互体验的增强工具

前端脚本运行在浏览器环境,主要用于扩展UI和响应用户操作。通过src/public/app/widgets/目录下的组件系统,你可以创建自定义界面元素。

// 前端小部件基础示例
class MyWidget extends api.NoteContextAwareWidget {
  render() {
    return `
      <div class="custom-widget">
        <h3>我的自定义工具</h3>
        <button onclick="api.showMessage('Hello')">点击我</button>
      </div>
    `;
  }
}

// 添加到右侧面板
api.addWidgetToRightPanel(MyWidget);

场景化解决方案

方案一:自动化知识图谱构建

需求:让笔记自动建立关联

你是否遇到过这样的情况:新添加一篇关于"机器学习"的笔记,却发现之前写的"神经网络"笔记没有关联?手动添加链接不仅繁琐,还容易遗漏重要关联。

实现思路

知识图谱构建需要两个核心步骤:首先提取笔记中的关键概念,然后基于这些概念寻找关联笔记并建立链接。

[输入] 新创建/更新的笔记 → [提取关键词] → [搜索相关笔记] → [创建关联] → [输出] 已建立关联的笔记

代码实现

// == 自动知识关联脚本 ==
// #run=backend
// #trigger=note-update

async function autoLinkNotes(event) {
  const note = event.note;
  
  // 跳过系统笔记和小笔记
  if (note.isSystemNote || note.type === 'text/x-tiddlywiki') return;
  
  // 提取关键词(简化版实现)
  const content = note.getContent();
  const keywords = extractKeywords(content);
  
  if (keywords.length === 0) return;
  
  // 搜索相关笔记
  const query = keywords.map(k => `text:"${k}"`).join(" OR ");
  const relatedNotes = await api.searchForNotes(query);
  
  // 建立关联
  api.transactional(() => {
    relatedNotes.forEach(relatedNote => {
      // 避免自关联和重复关联
      if (relatedNote.noteId !== note.noteId && 
          !hasExistingRelation(note, relatedNote)) {
        // 创建双向关联属性
        note.addRelationTo(relatedNote.noteId, "related");
        relatedNote.addRelationTo(note.noteId, "related");
        
        api.log(`建立关联: ${note.title}${relatedNote.title}`);
      }
    });
  });
}

// 提取关键词的辅助函数
function extractKeywords(content) {
  // 实际应用可使用NLP库提升准确性
  const stopWords = new Set(['的', '是', '在', '和', '有', '就', '这个', '我们']);
  const words = content.toLowerCase().match(/\b[\u4e00-\u9fa5]{2,}|\b[a-z]{3,}\b/g) || [];
  
  return Array.from(new Set(words))
    .filter(word => !stopWords.has(word))
    .slice(0, 5); // 取前5个关键词
}

// 检查是否已有关联
function hasExistingRelation(note, targetNote) {
  return note.getRelationsTo(targetNote.noteId, "related").length > 0;
}

// 注册事件监听器
api.onNoteUpdated(autoLinkNotes);

适用场景:个人知识库、学术研究笔记、学习笔记管理

注意事项:首次运行可能需要处理历史笔记,建议分批次执行以避免性能问题

扩展方向:可集成TF-IDF或TextRank算法提升关键词提取准确性,或添加关联强度评分系统

5分钟上手指南

  1. 创建新的代码笔记,设置MIME类型为"application/javascript"
  2. 添加属性#run=backend#trigger=note-update
  3. 复制上述代码并保存
  4. 创建或编辑一篇包含多个关键词的笔记
  5. 在笔记属性面板查看自动创建的"related"关联

方案二:网页内容智能抓取

需求:一键保存网页精华内容

你是否经常需要将网页内容保存到笔记,但又讨厌复制粘贴带来的格式混乱和冗余信息?手动整理一篇技术文章往往需要15-20分钟,而自动抓取可以将这个时间缩短到30秒。

实现思路

网页抓取需要解决三个问题:获取网页内容、提取关键信息、格式化保存。我们可以通过前端脚本创建一个抓取工具,让用户只需输入URL就能自动获取精华内容。

[输入] URL → [获取网页内容] → [提取标题/正文/图片] → [格式化] → [输出] 结构化笔记

代码实现

// == 智能网页抓取工具 ==
// #run=frontend

class WebClipperWidget extends api.BasicWidget {
  constructor() {
    super();
    this.state = {
      url: '',
      loading: false,
      result: null
    };
  }
  
  render() {
    return `
      <div class="web-clipper">
        <h3>智能网页抓取</h3>
        <div class="input-group">
          <input type="text" placeholder="输入URL" 
                 value="${this.state.url}" 
                 oninput="this.widget.setState({url: this.value})">
          <button onclick="this.widget.fetchWebpage()">
            ${this.state.loading ? '抓取中...' : '抓取'}
          </button>
        </div>
        
        ${this.state.result ? `
          <div class="result">
            <h4>${this.state.result.title}</h4>
            <p>${this.state.result.excerpt}</p>
            <button onclick="this.widget.saveToNote()">保存到笔记</button>
          </div>
        ` : ''}
      </div>
    `;
  }
  
  async fetchWebpage() {
    if (!this.state.url || this.state.loading) return;
    
    this.setState({loading: true});
    
    try {
      // 调用后端API获取网页内容
      const result = await api.runOnBackend(
        'webClipper.fetchPage', 
        {url: this.state.url}
      );
      
      this.setState({
        loading: false,
        result: {
          title: result.title,
          content: result.content,
          excerpt: result.content.substring(0, 150) + '...',
          url: this.state.url
        }
      });
    } catch (e) {
      this.setState({loading: false});
      api.showMessage(`抓取失败: ${e.message}`, 'error');
    }
  }
  
  async saveToNote() {
    if (!this.state.result) return;
    
    const {title, content, url} = this.state.result;
    
    // 创建新笔记
    const {note} = await api.runOnBackend(
      'webClipper.createNote',
      {
        parentNoteId: api.getActiveNote().noteId,
        title: title,
        content: `# ${title}\n\n${content}\n\n原文链接`,
        url: url
      }
    );
    
    api.activateNote(note.noteId);
    api.showMessage(`已保存笔记: ${title}`);
    this.setState({result: null, url: ''});
  }
}

// 添加到右侧面板
api.addWidgetToRightPanel(WebClipperWidget);

需要在后端添加对应的处理函数(src/services/backend_script_api.js):

// 后端API扩展
api.webClipper = {
  async fetchPage({url}) {
    const fetch = require('node-fetch');
    const cheerio = require('cheerio');
    
    const response = await fetch(url);
    const html = await response.text();
    const $ = cheerio.load(html);
    
    // 提取标题
    let title = $('title').text();
    
    // 提取正文(使用readability算法的简化实现)
    let content = '';
    $('p').each((i, el) => {
      content += $(el).text() + '\n\n';
    });
    
    return {title, content};
  },
  
  async createNote({parentNoteId, title, content, url}) {
    const {note} = api.createTextNote(parentNoteId, title, content);
    note.setLabel('source', 'web');
    note.setLabel('url', url);
    note.save();
    
    return {noteId: note.noteId, title: note.title};
  }
};

适用场景:研究资料收集、文章阅读管理、新闻摘要保存

注意事项:部分网站可能有反爬机制,可添加用户代理头或延迟请求避免被屏蔽

扩展方向:可添加自动分类功能,基于内容主题将抓取的笔记保存到对应分类下

5分钟上手指南

  1. 创建前端脚本笔记,添加代码并设置#run=frontend
  2. 修改src/services/backend_script_api.js添加后端处理函数
  3. 刷新Trilium界面,在右侧面板找到"智能网页抓取"工具
  4. 输入目标网页URL,点击"抓取"按钮
  5. 预览提取结果后点击"保存到笔记"

方案三:多维度笔记统计分析

需求:量化你的知识体系

你是否想知道自己的笔记主要集中在哪些主题?每周创建多少篇笔记?哪些笔记被引用次数最多?这些数据可以帮助你发现知识盲点和兴趣变化,但手动统计几乎不可能实现。

实现思路

统计分析需要从多个维度收集和展示数据:笔记数量随时间的变化、主题分布、关联密度等。我们可以创建一个定期运行的后端脚本生成统计数据,再通过前端组件展示可视化结果。

[输入] 笔记数据库 → [按维度聚合] → [生成统计数据] → [存储结果] → [前端展示]

代码实现

首先创建后端统计脚本:

// == 笔记统计分析工具 ==
// #run=backend
// #trigger=weekly

async function generateNoteStatistics() {
  // 1. 时间分布统计
  const monthlyCounts = await getMonthlyNoteCounts();
  
  // 2. 标签分布统计
  const tagStatistics = await getTagDistribution();
  
  // 3. 关联统计
  const relationStats = await getRelationStatistics();
  
  // 4. 活跃度统计
  const activityStats = await getUserActivity();
  
  // 存储统计结果
  const statsNote = await getOrCreateStatsNote();
  
  api.transactional(() => {
    statsNote.setContent(generateStatsHtml({
      monthlyCounts,
      tagStatistics,
      relationStats,
      activityStats,
      generated: new Date().toISOString()
    }));
    statsNote.save();
  });
  
  api.log("笔记统计已更新");
}

// 辅助函数:获取每月笔记数量
async function getMonthlyNoteCounts() {
  const notes = await api.searchForNotes("created:>=2020-01-01");
  const counts = {};
  
  notes.forEach(note => {
    const month = note.createdAt.substring(0, 7); // 格式: YYYY-MM
    counts[month] = (counts[month] || 0) + 1;
  });
  
  return counts;
}

// 辅助函数:获取标签分布
async function getTagDistribution() {
  const notes = await api.searchForNotes("");
  const tags = {};
  
  notes.forEach(note => {
    const noteTags = note.getLabels("tag");
    noteTags.forEach(tag => {
      tags[tag.value] = (tags[tag.value] || 0) + 1;
    });
  });
  
  // 返回前20个标签
  return Object.entries(tags)
    .sort((a, b) => b[1] - a[1])
    .slice(0, 20);
}

// 辅助函数:获取统计笔记或创建
async function getOrCreateStatsNote() {
  const statsNotes = await api.searchForNotes("#type:statistics");
  
  if (statsNotes.length > 0) {
    return statsNotes[0];
  } else {
    // 创建新的统计笔记
    const {note} = api.createTextNote(
      api.getRootNoteId(),
      "笔记统计分析",
      "正在生成统计数据..."
    );
    note.setLabel("type", "statistics");
    return note;
  }
}

// 生成统计HTML
function generateStatsHtml(stats) {
  return `
    <h1>笔记统计分析</h1>
    <p>生成时间: ${new Date(stats.generated).toLocaleString()}</p>
    
    <h2>月度笔记创建量</h2>
    <pre>${JSON.stringify(stats.monthlyCounts, null, 2)}</pre>
    
    <h2>标签分布</h2>
    <pre>${JSON.stringify(stats.tagStatistics, null, 2)}</pre>
  `;
}

// 执行统计
generateNoteStatistics();

然后创建前端展示组件:

// == 统计数据可视化组件 ==
// #run=frontend

class StatsVisualizationWidget extends api.NoteContextAwareWidget {
  async render() {
    // 查找统计笔记
    const statsNotes = await api.searchForNotes("#type:statistics");
    
    if (statsNotes.length === 0) {
      return `<div class="stats-widget">请先运行统计分析脚本</div>`;
    }
    
    const statsNote = statsNotes[0];
    const content = await statsNote.getContent();
    
    return `
      <div class="stats-widget">
        <h3>知识体系统计</h3>
        ${content}
        <button onclick="api.runOnBackend('generateNoteStatistics')">
          更新统计
        </button>
      </div>
    `;
  }
}

api.addWidgetToRightPanel(StatsVisualizationWidget);

适用场景:个人知识管理复盘、学习进度跟踪、内容创作分析

注意事项:统计大量笔记可能影响性能,建议设置为每周或每月运行一次

扩展方向:可添加知识图谱可视化,使用D3.js绘制笔记关联网络图

5分钟上手指南

  1. 创建后端统计脚本,添加#run=backend#trigger=weekly属性
  2. 创建前端可视化组件,添加#run=frontend属性
  3. 手动运行一次后端脚本生成初始数据
  4. 在右侧面板找到"知识体系统计"组件查看结果
  5. 根据统计数据调整你的知识管理策略

进阶探索:Trilium脚本开发进阶

与Python脚本自动化的对比

Trilium脚本与传统Python脚本自动化相比有几个关键差异:

特性 Trilium脚本 Python脚本
运行环境 内置在Trilium中 需要独立Python环境
访问权限 直接操作笔记数据库 通过API间接访问
响应速度 极快(无网络开销) 较慢(需网络请求)
部署难度 零配置 需要安装依赖
学习曲线 中等(JavaScript基础) 较低(Python生态丰富)

Trilium脚本更适合轻量级、实时性要求高的自动化任务,而Python脚本适合复杂数据处理和外部系统集成。

技术选型建议

根据不同自动化场景,选择合适的工具:

  1. 数据整理与关联:优先使用Trilium后端脚本,直接操作数据库
  2. 网页抓取与外部数据导入:结合Trilium脚本和Python,Python负责抓取,Trilium负责存储
  3. UI扩展与交互增强:使用Trilium前端脚本,开发自定义小部件
  4. 复杂数据分析:导出数据到CSV,使用Python Pandas或R进行分析
  5. 定时任务:简单任务使用#trigger属性,复杂任务考虑外部 cron + API调用

性能优化策略

  1. 批量操作使用事务:所有批量修改放在api.transactional()中执行
  2. 避免频繁搜索:缓存搜索结果,尤其是频繁使用的查询
  3. 事件驱动设计:使用触发器代替定时任务,减少资源消耗
  4. 分页处理大结果集:使用api.searchForNotes(query, {limit, offset})处理大量数据

总结

Trilium的脚本编程功能为知识管理带来了无限可能。通过本文介绍的三个案例,你已经掌握了从自动关联笔记、智能抓取网页到统计分析知识体系的核心技巧。这些工具不仅能帮你节省大量整理时间,更能让你的笔记系统主动为你提供知识支持。

记住,最好的知识管理工具不是静态的文件夹和标签,而是能够根据你的使用习惯不断进化的智能系统。现在就开始编写你的第一个Trilium脚本,让知识管理变得更高效、更智能!

未来你还可以探索更高级的应用,如集成AI摘要、构建自定义工作流、开发专用领域的知识处理工具等。Trilium的脚本引擎就像一个开放的实验场,等待你用创意和代码来打造属于自己的第二大脑。

登录后查看全文