iBook/detaildesign.md

7.1 KiB
Raw Blame History

iBooks 笔记导出工具 详细设计文档

1. 概述

本工具用于从 macOS iBooksApple Books应用的数据文件中提取用户的书籍笔记并以 Markdown 格式导出。支持从 iBooks 的数据库和 plist 文件自动同步数据,支持交互式选择书籍导出,导出内容结构清晰,便于后续整理和阅读。 支持按最近打开时间排序书籍,菜单显示书名与时间戳,导出流程高效。


2. 主要功能

  • 自动同步 iBooks 数据库和书籍信息文件到本地 ./data 目录。
  • 解析 iBooks 笔记数据库,构建结构化的 booksnote 数据。
  • 解析书籍元数据(如书名、路径等)。
  • 支持交互式模糊搜索选择要导出的书籍。
  • 按章节导出所选书籍的所有笔记,格式为 Markdown。
  • 书名中如含有“-xxxx”后缀仅保留“-”前的主书名。
  • 书籍选择菜单按最近打开时间last_open降序排序显示格式为“书名 [时间戳]”。

3. 主要数据结构

3.1 booksnote

booksnote = {
  assetid: { label_path: { uuid: {
      'creationdate': '2023/7/12',
      'filepos': None,
      'idref': '008.xhtml',
      'note': None,
      'selectedtext': '這就是宣傳的恐怖之處'
      }}}
}
  • assetid:书籍唯一标识
  • label_path:章节名
  • uuid:笔记唯一标识
  • 其余字段为笔记内容及元数据

4. 主要流程

4.1 数据同步

  • 自动将 iBooks 的数据库和 plist 文件复制到本地 data/ 目录,便于后续处理。

4.2 构建 booksnote

  • 通过 get_annotations 解析 SQLite 笔记数据库,获取所有笔记。
  • 通过 parse_books_plist 解析书籍元数据,获取书名、路径等信息。
  • 遍历每本书的所有笔记结合OPF、NCX文件和HTML 文件,定位章节名。
  • 若无法通过目录文件定位章节,则尝试通过笔记选中文本在 HTML 文件中查找章节,否则标记为“未找到章节”。

4.3 交互式选择书籍

  • 读取 Books.plist 获取所有书籍元数据。
  • 读取 BKLibrary.sqlite获取每本书的最近打开时间last_open苹果时间戳基准2001-01-01
  • 生成书名列表(优先 displayname,其次 itemname,否则用 assetid),并去除“-xxxx”后缀。
  • 按 last_open 时间戳降序排列,菜单显示“书名 [时间戳]”,时间戳为 last_open 字段。
  • 使用 InquirerPy 提供模糊搜索交互界面,供用户选择要导出的书籍。

4.4 导出 Markdown

  • 仅导出用户选择的书籍。

  • Markdown 格式如下:

    # 笔记导出 2025-08-06 12:00
    ## 书名
    ### 章节名
    选中文本
    > 笔记内容
    
  • 每条笔记独立分行,章节分组。


5. 关键函数说明

5.1 build_booksnote

  • 输入:注释数据库路径、书籍 plist 路径
  • 输出:结构化的 booksnote 字典
  • 逻辑:遍历所有笔记,结合书籍元数据和目录信息,归类到章节下

5.2 export_booksnote_to_md

  • 输入booksnote、booksinfo、导出路径
  • 输出Markdown 字符串,并写入文件
  • 逻辑:遍历每本书、每个章节、每条笔记,按格式输出

6. 交互与用户体验

  • 通过命令行交互,用户可模糊搜索并选择要导出的书籍。
  • 若无可导出的笔记,程序自动退出并提示。
  • 导出后,显示导出文件路径和书名。

7. 代码片段示例

7.1 书名处理逻辑

name = info.get('displayname') or info.get('itemname') or assetid
# 如果书名中包含“-”,只取“-”前面的部分
if '-' in name: name = name.split('-', 1)[0].strip()

7.2 交互式选择与排序

from booklist_parse import get_books_last_open
last_open_times = get_books_last_open('data/BKLibrary.sqlite')
for assetid, info in booksinfo.items():
    ...
    ts = last_open_times.get(assetid, {}).get('last_open', 0)
    assetid2lastopen[assetid] = ts
sorted_assetids = sorted(assetid2name.keys(), key=lambda aid: assetid2lastopen[aid], reverse=True)
choices = [f"{assetid2name[aid]} [{assetid2lastopen[aid]}]" for aid in sorted_assetids]
answer = inquirer.fuzzy(
    message="请选择要导出的书名(支持模糊搜索):",
    choices=choices,
    multiselect=False,
    instruction="上下键选择,输入可模糊筛选,回车确定"
).execute()

8. 依赖说明

  • Python 3
  • 主要依赖库:InquirerPy, bs4, shutil, os, datetime, sqlite3
  • 需有 iBooks 数据库、plist 文件和 BKLibrary.sqlite 的本地访问权限

9. 目录结构

  • data/:存放同步下来的数据库和 plist 文件(含 AEAnnotation.sqlite、Books.plist、BKLibrary.sqlite 等)
  • export_notes/:导出的 Markdown 文件
  • examples/epub 示例文件夹

9.1 主要代码文件说明(细化)

  • exportbooknotes.py

    • 采用 OOP 设计,核心类为 BookNotesExporter
      • build_booksnote(bookid=None):构建结构化笔记数据。
      • export_booksnote_to_md(booksnote, booksinfo, out_path=None):导出为 Markdown。
      • find_file_by_extget_toc_tree 等辅助方法。
    • 数据同步:自动复制 iBooks 数据库和元数据到本地。
    • 菜单交互:按最近打开时间戳排序,显示“书名 [时间戳]”,支持模糊搜索。
    • 只处理用户选中书籍的笔记,按章节分组导出 Markdown。
    • 依赖核心解析模块,负责主流程调度。
  • annotationdata.py

    • OOP 设计,核心类为 AnnotationManager
      • get_annotations(bookid=None):返回所有或指定 assetid 的笔记。
      • parse_location(location):静态方法,解析定位信息。
    • 解析 AEAnnotation.sqlite提取所有或指定 assetid 的笔记。
    • 支持苹果时间戳转换,结构化输出。
  • booklist_parse.py

    • OOP 设计,核心类为 BookListManager
      • get_books_info():获取书籍元数据。
      • get_books_last_open():获取每本书的最近打开时间。
    • 解析 Books.plist获取书籍元数据书名、作者、路径、时间等
    • 解析 BKLibrary.sqlite获取每本书的最近打开时间。
  • opf_parse.py

    • OOP 设计,核心类为 OPFParser
      • parse_opf(filepath):静态方法,返回 id->href 映射。
    • 解析 epub 的 OPF 文件获取章节与文件映射关系idref -> href
  • toc_parse.py

    • OOP 设计,核心类为 TOCParser
      • parse_navpoints(navpoints):递归解析 navPoint 节点。
      • find_label_path(node, ref, filepos, path):查找章节路径。
      • find_section_by_selectedtext(html_path, selectedtext):通过选中文本定位章节标题。
      • parse_html_title(html_path):解析 html 文件标题。
    • 解析 NCX 目录文件,递归构建章节树结构。
  • backup/booksnote.py

    • 历史/备份脚本,辅助数据迁移或格式转换。

10. 扩展与维护建议

  • 可扩展支持多本书批量导出
  • 可增加导出格式(如 HTML、PDF
  • 可优化章节定位算法,提升准确率
  • 可增加 GUI 交互界面

如需进一步细化某一部分设计,请告知!