This commit is contained in:
douboer
2025-10-21 10:46:03 +08:00
parent db9be32815
commit fb0f5ed9c5
20 changed files with 1869 additions and 103 deletions

149
readme.md
View File

@@ -1,6 +1,6 @@
# iBooks 笔记专家 详细设计文档
> 版本: 1.1 (2025-09 重构整理)
> 版本: 1.2 (2025-10 CFI排序与优化)
> 维护者: 项目开发组
> 说明: 本文档统一重新编排章节,增加架构与 UML 部分,便于后续扩展与维护。
@@ -8,11 +8,19 @@
|------|------|------|
| 1.0 | 2025-08 | 初版文档 |
| 1.1 | 2025-09 | 重组目录新增模块拆分、UML、AI 简评与可视化章节整理 |
| 1.2 | 2025-10 | **重大更新**: EPUB CFI排序系统界面优化性能提升 |
## 1. 概述
本工具用于从 macOS iBooksApple Books应用的数据文件中提取用户的书籍笔记并以 Markdown 格式导出。支持从 iBooks 的数据库和 plist 文件自动同步数据,支持交互式选择书籍导出,导出内容结构清晰,便于后续整理和阅读。
支持按最近打开时间排序书籍,菜单显示书名与时间戳,导出流程高效。
本工具用于从 macOS iBooksApple Books应用的数据文件中提取用户的书籍笔记并以 Markdown 格式导出。**v1.2版本重大改进**实现完整的EPUB CFICanonical Fragment Identifier排序系统确保笔记按真实阅读位置排序,支持交互式选择书籍导出,导出内容结构清晰,便于后续整理和阅读。
### 🆕 v1.2 新特性
- **🎯 EPUB CFI 排序**: 完整实现IDPF规范笔记按文档真实位置排序
- **📊 阅读统计修复**: 7天/30天/年度阅读时长统计准确性提升
- **🎨 界面优化**: 清理控制台警告,改进按钮交互效果
- **⚡ 性能提升**: 优化数据处理流程,减少冗余计算
- **🧪 测试覆盖**: 全面的CFI解析、排序、导出验证测试
---
@@ -22,11 +30,27 @@
- 自动同步 iBooks 数据库和书籍信息文件到本地 `./data` 目录。
- 解析 iBooks 笔记数据库,构建结构化的 `booksnote` 数据。
- **🆕 EPUB CFI 排序**: 按 EPUB 规范解析 CFI 位置信息,确保笔记按真实阅读顺序排列。
- 解析书籍元数据(如书名、路径等)。
- 支持交互式模糊搜索选择要导出的书籍。
- 按章节导出所选书籍的所有笔记,格式为 Markdown。
- 书名中如含有-xxxx后缀,仅保留“-”前的主书名。
- 书籍选择菜单按最近打开时间last_open降序排序显示格式为书名 [时间戳]
- 书名中如含有"-xxxx"后缀,仅保留"-"前的主书名。
- 书籍选择菜单按最近打开时间last_open降序排序显示格式为"书名 [时间戳]"
- **🆕 阅读统计**: 精确的7天/30天/年度阅读时长统计和可视化图表。
### 2.1.1 CFI 排序技术
EPUB CFI (Canonical Fragment Identifier) 是 IDPF 制定的标准,用于精确定位 EPUB 文档中的位置:
```
epubcfi(/6/22[id19]!/4[section]/40/1,:96,:214)
```
- **Spine 路径** (`/6/22`): 文档结构中的章节位置
- **Local 路径** (`/4[section]/40/1`): 章节内的元素位置
- **字符偏移** (`:96,:214`): 文本内的精确字符范围
v1.2 实现完整的 CFI 解析和排序算法,确保笔记按真实阅读顺序而非字符串顺序排列。
## 2.1 GUI
@@ -67,9 +91,12 @@
## 4. 主要数据结构
### 4.1 booksnote
### 4.1 booksnote (v1.2 CFI 排序优化)
**v1.2 数据结构变更**:为支持 CFI 排序,`annotations` 数据结构从嵌套字典改为列表格式:
```python
# v1.1 及之前版本
booksnote = {
assetid: { label_path: { uuid: {
'creationdate': '2023/7/12',
@@ -79,11 +106,28 @@ booksnote = {
'selectedtext': '這就是宣傳的恐怖之處'
}}}
}
# v1.2 CFI 排序版本
annotations = {
assetid: [ # 按 CFI 位置排序的列表
{
'uuid': 'annotation_id',
'creationdate': '2023-07-12 14:30:00',
'location': 'epubcfi(/6/22[id19]!/4[section]/40/1,:96,:214)',
'chapter_info': '章节_id19',
'note': '用户笔记内容',
'selectedtext': '選中的文本',
'physical_location': 1250 # 备用排序
}
]
}
```
- `assetid`:书籍唯一标识
- `label_path`:章节名
- `uuid`:笔记唯一标识
- 其余字段为笔记内容及元数据
**关键改进**
- **CFI 位置字段**: `location` 存储完整的 EPUB CFI 字符串
- **章节信息**: `chapter_info` 自动解析的可读章节名称
- **排序保证**: 列表已按 CFI 位置预排序,确保阅读顺序正确
- **兼容性**: 保持向后兼容,自动适配新数据结构
---
@@ -93,12 +137,30 @@ booksnote = {
- 自动将 iBooks 的数据库和 plist 文件复制到本地 `data/` 目录,便于后续处理。
### 5.2 构建 booksnote
### 5.2 构建 booksnote (v1.2 CFI 排序优化)
- 通过 `get_annotations` 解析 SQLite 笔记数据库,获取所有笔记。
- 通过 `AnnotationManager.get_annotations()` 解析 SQLite 笔记数据库,获取所有笔记。
- **🆕 CFI 排序处理**
- 使用 `EpubCFIParser` 解析每条笔记的 `ZANNOTATIONLOCATION` 字段
- 提取 spine 路径、local 路径和字符偏移信息
- 按 CFI 语义顺序排序,确保笔记按真实阅读位置排列
- 降级处理CFI 解析失败时使用物理位置和创建时间排序
- 通过 `parse_books_plist` 解析书籍元数据,获取书名、路径等信息。
- 遍历每本书的所有笔记结合OPF、NCX文件和HTML 文件,定位章节名。
- 若无法通过目录文件定位章节,则尝试通过笔记选中文本在 HTML 文件中查找章节,否则标记为未找到章节
- 若无法通过目录文件定位章节,则尝试通过笔记选中文本在 HTML 文件中查找章节,否则标记为"未找到章节"
#### CFI 排序技术流程
```mermaid
graph LR
A[笔记数据] --> B[CFI解析]
B --> C{解析成功?}
C -->|是| D[CFI排序键]
C -->|否| E[物理位置+时间]
D --> F[按位置排序]
E --> F
F --> G[有序笔记列表]
```
### 5.3 交互式选择书籍
@@ -125,19 +187,62 @@ booksnote = {
---
## 6. 关键函数说明
## 6. 核心模块架构 (v1.2)
### 6.1 build_booksnote
### 6.1 主要模块
- 输入:注释数据库路径、书籍 plist 路径
- 输出:结构化的 booksnote 字典
- 逻辑:遍历所有笔记,结合书籍元数据和目录信息,归类到章节下
| 模块 | 功能 | v1.2 更新 |
|------|------|----------|
| `annotationdata.py` | 笔记数据库接口 | **重构** CFI 排序集成 |
| `epub_cfi_parser.py` | **🆕 新增** CFI 解析引擎 | IDPF 规范完整实现 |
| `booklist_parse.py` | 书籍元数据与统计 | 适配新数据结构 |
| `exportbooknotes.py` | 笔记导出功能 | 支持CFI排序列表 |
| `ibook_export_app.py` | 主GUI应用 | 界面优化,统计修复 |
| `charts.py` | 统计图表组件 | 性能优化 |
### 6.2 export_booksnote_to_md
### 6.2 关键函数说明
- 输入booksnote、booksinfo、导出路径
- 输出Markdown 字符串,并写入文件
- 逻辑:遍历每本书、每个章节、每条笔记,按格式输出
#### 6.2.1 AnnotationManager.get_annotations (CFI 排序)
```python
def get_annotations(self, bookid=None) -> dict:
"""
返回按 CFI 位置排序的笔记数据
Returns:
{assetid: [annotations_list]} # v1.2 列表格式
"""
```
- **输入**书籍ID可选
- **输出**:按 CFI 排序的笔记列表字典
- **v1.2 改进**
- 集成 `EpubCFIParser` 进行位置解析
- 自动章节信息提取
- 多级排序键CFI → 物理位置 → 创建时间
#### 6.2.2 EpubCFIParser (新增模块)
```python
class EpubCFIParser:
@staticmethod
def parse_cfi(cfi_string: str) -> tuple:
"""解析 CFI 字符串为结构化数据"""
@staticmethod
def create_sort_key(cfi_string: str) -> tuple:
"""创建 CFI 排序键"""
@staticmethod
def extract_chapter_info(cfi_string: str) -> str:
"""提取可读的章节信息"""
```
#### 6.2.3 export_booksnote_to_md (适配更新)
- **输入**CFI 排序的 annotations、booksinfo、导出路径
- **输出**Markdown 字符串,并写入文件
- **v1.2 改进**:适配新的列表数据结构,保持导出格式兼容
---