# iBooks 笔记导出工具 详细设计文档 ## 1. 概述 本工具用于从 macOS iBooks(Apple Books)应用的数据文件中提取用户的书籍笔记,并以 Markdown 格式导出。支持从 iBooks 的数据库和 plist 文件自动同步数据,支持交互式选择书籍导出,导出内容结构清晰,便于后续整理和阅读。 支持按最近打开时间排序书籍,菜单显示书名与时间戳,导出流程高效。 --- ## 2. 主要功能 - 自动同步 iBooks 数据库和书籍信息文件到本地 `./data` 目录。 - 解析 iBooks 笔记数据库,构建结构化的 `booksnote` 数据。 - 解析书籍元数据(如书名、路径等)。 - 支持交互式模糊搜索选择要导出的书籍。 - 按章节导出所选书籍的所有笔记,格式为 Markdown。 - 书名中如含有“-xxxx”后缀,仅保留“-”前的主书名。 - 书籍选择菜单按最近打开时间(last_open)降序排序,显示格式为“书名 [时间戳]”。 --- ## 3. 主要数据结构 ### 3.1 booksnote ```python 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 书名处理逻辑 ```python name = info.get('displayname') or info.get('itemname') or assetid # 如果书名中包含“-”,只取“-”前面的部分 if '-' in name: name = name.split('-', 1)[0].strip() ``` ### 7.2 交互式选择与排序 ```python 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_ext`、`get_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 交互界面 --- 如需进一步细化某一部分设计,请告知!