This commit is contained in:
douboer
2025-08-15 17:20:30 +08:00
parent 0bc6844209
commit 4e3b8abc34
12 changed files with 406 additions and 516 deletions

View File

@@ -1,75 +1,66 @@
"""
booklist_parse.py
-----------------
功能:
- 解析iBooks的Books.plist提取所有书籍元数据书名、作者、路径、时间等
- 解析BKLibrary.sqlite获取每本书的最近打开时间苹果时间戳基准2001-01-01
依赖config.py 统一管理路径和配置项。
主要接口:
- parse_books_plist(plist_path):返回所有书籍元数据,结构为{bk_id: {...}}
- get_books_last_open(db_path):返回所有书籍最近打开时间,结构为{bk_id: {'last_open': 时间戳}}
依赖plistlib, collections, sqlite3, os, datetime
典型用法:
booksinfo = parse_books_plist(config.LOCAL_BOOKS_PLIST)
books_open = get_books_last_open(config.LOCAL_LIBRARY_DB)
"""
import config
import plistlib
from collections import defaultdict
def parse_books_plist(plist_path=config.LOCAL_BOOKS_PLIST):
booksinfo = defaultdict(dict)
with open(plist_path, 'rb') as f: plist_data = plistlib.load(f)
for book in plist_data.get('Books', []):
bk_id = book.get('BKGeneratedItemId')
if not bk_id: continue
booksinfo[bk_id] = {
'displayname': book.get('BKDisplayName', ''),
'author': book.get('artistName', ''),
'type': book.get('BKBookType', ''),
'bookid': bk_id,
'itemname': book.get('itemName', ''),
'path': book.get('path', ''),
'date': book.get('BKInsertionDate',''),
'updatedate': book.get('updateDate','')
}
return booksinfo
import sqlite3
import os
from collections import defaultdict
def get_books_last_open(db_path=config.LOCAL_LIBRARY_DB):
"""
从BKLibrary.sqlite获取书籍最近打开时间
返回defaultdict(dict)bk_id为索引包含最近打开时间
"""
books_open = defaultdict(dict)
if not os.path.exists(db_path):
class BookListManager:
def __init__(self, plist_path=None, db_path=None):
self.plist_path = plist_path or config.LOCAL_BOOKS_PLIST
self.db_path = db_path or config.LOCAL_LIBRARY_DB
self._booksinfo = None
self._books_open = None
def get_books_info(self):
if self._booksinfo is not None:
return self._booksinfo
booksinfo = defaultdict(dict)
with open(self.plist_path, 'rb') as f:
plist_data = plistlib.load(f)
for book in plist_data.get('Books', []):
bk_id = book.get('BKGeneratedItemId')
if not bk_id:
continue
booksinfo[bk_id] = {
'displayname': book.get('BKDisplayName', ''),
'author': book.get('artistName', ''),
'type': book.get('BKBookType', ''),
'bookid': bk_id,
'itemname': book.get('itemName', ''),
'path': book.get('path', ''),
'date': book.get('BKInsertionDate',''),
'updatedate': book.get('updateDate','')
}
self._booksinfo = booksinfo
return booksinfo
def get_books_last_open(self):
if self._books_open is not None:
return self._books_open
books_open = defaultdict(dict)
if not os.path.exists(self.db_path):
return books_open
try:
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute(''' SELECT ZASSETID, zlastopendate FROM ZBKLIBRARYASSET WHERE zlastopendate IS NOT NULL ''')
rows = cursor.fetchall()
for row in rows:
asset_id, last_open = row
if asset_id:
books_open[asset_id] = {
'last_open': last_open
}
conn.close()
except Exception as e:
print(f'警告: 读取BKLibrary.sqlite失败: {e}')
self._books_open = books_open
return books_open
try:
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# ZBKLIBRARYASSET表包含书籍信息
cursor.execute(''' SELECT ZASSETID, zlastopendate FROM ZBKLIBRARYASSET WHERE zlastopendate IS NOT NULL ''')
rows = cursor.fetchall()
for row in rows:
asset_id, last_open = row
if asset_id:
books_open[asset_id] = {
'last_open': last_open # 苹果时间戳基准时间为2001-01-01
}
conn.close()
except Exception as e:
print(f'警告: 读取BKLibrary.sqlite失败: {e}')
return books_open
if __name__ == '__main__':
booksinfo = parse_books_plist(config.LOCAL_BOOKS_PLIST)
manager = BookListManager()
booksinfo = manager.get_books_info()
from pprint import pprint
print("\n【前三条示例】")
for k, v in list(booksinfo.items())[:3]:
@@ -77,19 +68,10 @@ if __name__ == '__main__':
pprint(v, sort_dicts=False, indent=2)
print('-' * 60)
'''
print("\n【全部内容】")
for k, v in booksinfo.items():
print(f"{k}:")
pprint(v, sort_dicts=False, indent=2)
print('-' * 60)
'''
# 测试最近打开时间
print("\n【最近打开时间示例】")
books_open = get_books_last_open()
books_open = manager.get_books_last_open()
import datetime
for k, v in list(books_open.items())[:3]:
ts = v['last_open']
# 苹果时间戳基准2001-01-01
dt = datetime.datetime(2001, 1, 1) + datetime.timedelta(seconds=ts)
print(f"{k}: {dt} (timestamp: {ts})")