iBook/detaildesign.md

214 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# iBooks 笔记导出工具 详细设计文档
## 1. 概述
本工具用于从 macOS iBooksApple 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 交互界面
---
如需进一步细化某一部分设计,请告知!