OneNote → ima 迁移技能
把「导出 → 合并 → 清洗 → 导入包 → (可选)上传 → 对账」固化下来,避免每次都重新踩坑。
它不是又一个导出脚本。 全网同类工具基本止步于"能导出 md",本技能额外解决真实大规模迁移里才会出现的问题:
OneNote COM 连续导出崩溃、启动弹框挂死 COM、笔记本缓存损坏、多批次重复合并、分区到知识库文件夹的映射、
以及导入后逐层对账。目标是可断点、可对账、可重跑——迁移不必一次成功。
已验证:一次真实迁移 395 页 → 清洗后 371 篇全量入库 ima,逐层对账一致、检索命中正常、无 PARSE_ERROR。
适用边界
能做
- Windows + 桌面版 OneNote(ONENOTE.EXE,提供 COM;UWP 版 ONENOTEM.EXE 没有 COM)
- 本地或 OneDrive 云端笔记本(云端需已同步到本地)
- 产物:Markdown(图片留本地)
- 输出可直接拖入 ima 客户端的目录包;可选生成 MCP 上传计划由 agent 执行
不能做(明确拒绝并给替代)
- macOS(无 COM)→ ① OneNote 网页版导出 PDF 后走 ima 通用文档导入;② 或试用 strick-j/onenote-exporter(GitHub,macOS 上解析 .one)
- 不装桌面版 OneNote / 无法用 COM → 可关注 Kev744/py-onenote-parser(GitHub,纯 Python 解析 .one,本技能未集成)
- 自动打标签:ima MCP 没有写标签接口,只能产出打标清单(tag_checklist.csv)供客户端手工打
- 页级增量 diff:用「全量重跑 + 内容 sha1 去重」替代
- 删除/移动 ima 已入库条目:MCP 无此能力,只能产出待处理清单
- 图片随文入库:ima 单文件导入不带图,默认 image_policy=keep-local 把图留本地并出报告清单
安装前置(一次)
- onenote-md-exporter ≥ 1.6.0(GPL-3.0,独立进程调用,本技能不复制其代码)
从 <https://github.com/alxnbl/onenote-md-exporter/releases> 下载解压到任意目录。
发布包已自带 pandoc.exe,无需单独安装。基于 .NET 10 编写,本机 .NET 8/9 实测可跑(非官方保证)。 - Python 3.9+ 与 pywin32:
pip install pywin32(仅 Windows 需要,用于窗口枚举)。无 numpy 等重依赖。 - 配置:
exporter_dir留空即可自动探测(见下),或显式指定;推荐把配置放在技能目录之外,
例如~/.workbuddy/onenote2ima-config.json,避免个人知识库 ID 被打包进技能。
exporter_dir 探测顺序:配置值 → 环境变量 ONENOTE_MD_EXPORTER_DIR → 「技能目录」/tools/onenote-md-exporter
→ ~/.workbuddy/tools/onenote-md-exporter → ~/tools/onenote-md-exporter → 当前目录下的 onenote-md-exporter。
都找不到时 preflight 会打印下载链接与放置路径,而不是抛堆栈。
快速开始
S=~/.workbuddy/skills/onenote2ima/scripts/onenote2ima.py
C=~/.workbuddy/onenote2ima-config.json
python $S selftest # 离线自检,不碰 OneNote(约 10s),先跑这个
python $S preflight --config $C # 前置校验
python $S all --config $C --out ./out # 导出→合并→清洗→打包→上传计划
python $S plan --config $C --out ./out # 单独生成 upload_plan.json(agent 用来调 MCP)
python $S record --plan ./out/package/upload_plan.json --results results.json --state ./out/package/upload_state.json
python $S verify --manifest ./out/package/manifest.json --actual actual_counts.json
目录结构
onenote2ima/
├── SKILL.md
├── README.md / CHANGELOG.md
├── config.example.json 模板(不含任何个人 ID,可直接抄)
├── references/
│ ├── troubleshooting.md COM 错误码、崩溃治理、图片路径
│ ├── ima-mcp.md ima MCP 能力边界、上传参数、对账口径
│ └── config-reference.md 配置字段与分区→文件夹映射
└── scripts/
├── onenote2ima.py CLI 入口
└── lib/ config / fsutil / exporter / merger / cleaner / packager / uploader / report / selftest
流程与关键约束
| 阶段 | 做什么 | 关键约束 |
|---|---|---|
| S0 preflight | 检查 OneNote 进程/弹框、exporter、配置、磁盘 | 存在「您希望如何启动 OneNote?」弹框时直接中止并提示用户点掉 |
| S1 export | 分区级导出(不是逐页) | 崩溃后先重启 OneNote 再重试该分区;成片失败提示「删除笔记本缓存 + 重新同步」 |
| S2 merge | 多批次合并、sha1 去重、按输出深度重写图片相对路径 | 合并后抽样 20 个图片引用必须可解析,否则中止 |
| S3 clean | 清 HTML 残留、死图标记、空页剔除、YYYYMMDD-主题-类型.md 命名、tags 注入 |
死图替换为 <!-- 图片缺失: xxx -->,不静默丢;空页原件留 _excluded/ |
| S4 package | 生成 package/(分区即一级目录)+ manifest.json |
目标非空需 --force |
| S5 plan | 生成 upload_plan.json(含 kb_id/folder_id/幂等 sha1) |
Python 不能直接调 ima MCP,必须由 agent 执行 |
| S6 verify | 用 agent 回填的真实计数对账 | ima 的 file_number 含子文件夹,真实文件数 = file_number - folder_number |
已知坑(务必遵守,详见 references/troubleshooting.md)
- 崩溃成串:连续导出 40+ 页会把 OneNote 拖崩,崩溃后再启动会弹模态框并彻底挡住 COM。
因此导出按分区进行,单分区失败只重试该分区;不要逐页高频调用。 - 缓存损坏:大面积
0x80042014或反复崩溃 ⇒ 让用户在弹框选「删除笔记本缓存」,等同步完成后重跑。 - 图片相对路径:导出产物里是
../../resources/x.png(相对 导出目录/笔记本/分区/页.md)。
合并后层级少一层,必须按输出深度重算,否则全库断链。 Sequence contains no elements:个别页(多为带附件页)工具无法导出,记入_failed/,需 OneNote 内另存。- 图片不会随 md 进 ima:单文件导入不带图。图片留本地
resources/,报告列「图片密集页 Top10」。 file_number语义:ima 返回的文件夹file_number= 直接子项数(含子文件夹),对账要减folder_number。
失败重试与回滚
- 分区级重试:S1 中单分区失败且
retryable=true时,自动taskkill后重启 OneNote 再重试该分区(--max-retry)。 - 不删原件:全流程只读 OneNote,只在
<out>/下写入;空页与失败页分别移入_excluded/、_failed/,原始导出目录不被改动。 - 幂等重跑:
upload_state.json按 sha1 记账,重复plan自动跳过已传;merge按正文 sha1 去重,重跑不会翻倍。 - 回滚:任一阶段失败即中止并保留中间产物,可直接从该阶段重跑(如
merge → clean → package),无需从头导出。
配置
抄 config.example.json 为用户级配置。字段:notebook、exporter_dir、exclude_sections、section_type、
kb_id、folder_map、default_folder、min_chars、image_policy。完整说明见 references/config-reference.md。
测试
python scripts/onenote2ima.py selftest 会在临时目录造 2 个假导出批次(覆盖正常页/空页/死图页/嵌套子页/非法字符标题/重复内容),
跑 merge→clean→package,断言:命名格式、空页剔除、死图标记、图片引用可解析、去重生效、manifest 条目数。当前 18/18 通过。
参考
references/troubleshooting.md— COM 错误码表、崩溃与缓存治理、图片路径规则references/ima-mcp.md— ima MCP 能力边界、上传两步、COS 校验、对账口径references/config-reference.md— 配置字段、分区→文件夹映射、标签维度