把两千首歌的播放列表塞进本地检索:我踩过的坑

场景是这样的:我把自己从 2016 年起攒的播放列表导出成 CSV,大概 2300 多首,字段有标题、艺人、专辑、时长、添加日期,还有一列我早期随手写的备注。目标是做成本地可检索的小库,能按「艺人 + 年份 + 备注关键词」查,顺便统计自己每年听歌的口味漂移。环境是 macOS 上的 Python 3.11 + SQLite,不联网,纯本地。

做法很土,先建表再灌数据:

import sqlite3, csv
con = sqlite3.connect("tracks.db")
con.execute("""CREATE TABLE IF NOT EXISTS tracks (
  id INTEGER PRIMARY KEY, title TEXT, artist TEXT, album TEXT,
  duration INTEGER, added TEXT, note TEXT)""")
with open("playlist.csv", newline="", encoding="utf-8-sig") as f:
    rows = [(r["title"], r["artist"], r["album"],
             int(r["duration_ms"]) // 1000, r["added"], r["note"])
            for r in csv.DictReader(f)]
con.executemany("INSERT INTO tracks (title,artist,album,duration,added,note) VALUES (?,?,?,?,?,?)", rows)
con.commit()

查询就直接上 SQL,艺人名做 LIKE,年份用 strftime('%Y', added)。检索「某艺人某年」大概 30ms 内出结果,够用了。

为什么不上全文索引或者向量检索:2300 行这个量级,SQLite 全表扫就是毫秒级,加 FTS5 反而多一层同步负担,CSV 一更新就得重建。代价是标题里的错别字和艺人别名查不到,我接受,因为我主要在按艺人筛。

真正失效的地方有三处。第一,导出的 CSV 里同一首歌会因为出现在多个列表里重复,我一开始没去重,统计「每年新增」直接虚高,后来按 title + artist 建了唯一索引才压住。第二,added 字段格式不统一,有的带时区有的不带,strftime 直接返回 NULL,我是先手动清洗成 ISO 日期再入库的。第三,备注列里我自己写过中文逗号和英文逗号混用,LIKE '%关键词%' 没问题,但想按逗号拆标签就全乱了,这部分我至今没处理干净。

还有一个坑是编码。Windows 上导出的那份带 BOM,第一次读进来标题前面多了个不可见字符,按标题精确匹配死活对不上,换成 utf-8-sig 才正常。这种问题不看 hexdump 根本发现不了。

现在这个库我主要用来回答一个问题:某张专辑我是哪一年开始听的。你们导出播放列表的时候,是怎么处理同一首歌跨多个列表重复的?是按标题去重还是带上艺人一起?

0
赞同度 100% · 0 条评论 · 9 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。