95 lines
3.3 KiB
Python
95 lines
3.3 KiB
Python
"""
|
||
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
|
||
|
||
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):
|
||
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)
|
||
from pprint import pprint
|
||
print("\n【前三条示例】")
|
||
for k, v in list(booksinfo.items())[:3]:
|
||
print(f"{k}:")
|
||
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()
|
||
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})") |