频道 2.1 万条评论灌进本地库,我被长度字段坑了一晚上
场景:自己的频道,2.1 万条评论,从 YouTube Data API v3 的 commentThreads 分页拉下来,存成 JSON 分批落盘。环境是 macOS + Python 3.11,目标是把它们塞进本地 SQLite,做按视频、按时间、按作者聚合,顺便试一下 LIKE 能不能撑住中文搜索。数据量不大,单表 2 万行,理论上几秒钟的事。
第一次跑就出问题:2.1 万条里有 137 条插入时报 string or blob too big,另有几十条评论正文变成半截。原因不是 API 限流,是我在写库前做了一次「清洗」,把换行和多余空白压掉,用了 text[:500] 这种截断。中文评论里混着 emoji、日文、韩文,Python 的切片按码点走,截在代理对中间,SQLite 那边就炸了。
做法改成先按字节判断,再按码点截,并且把原始 JSON 原文一块存下来,方便回查:
import json, sqlite3
def safe_clip(s, max_bytes=2000):
b = s.encode('utf-8')
if len(b) <= max_bytes:
return s
return b[:max_bytes].decode('utf-8', errors='ignore')
con = sqlite3.connect('comments.db')
con.execute('''CREATE TABLE IF NOT EXISTS c(
id TEXT PRIMARY KEY, vid TEXT, author TEXT, published TEXT,
text TEXT, raw TEXT)''')
for row in rows:
con.execute('INSERT OR REPLACE INTO c VALUES(?,?,?,?,?,?)', (
row['id'], row['vid'], row['author'], row['published'],
safe_clip(row['text']), json.dumps(row, ensure_ascii=False)))
con.commit()
为什么这样:SQLite 的 TEXT 没有硬上限,但单条记录受 SQLITE_MAX_LENGTH 约束,默认 1e9 字节,真正卡住我的是截断时产生的非法 UTF-8。errors='ignore' 会丢字符,代价是评论末尾可能少一两个字,所以原文必须另存一列 raw,后面要还原随时能还原。
哪里会失效:errors='ignore' 在截断点落在多字节字符中间时,会静默吞掉那半个字符,如果你的分析依赖精确字数统计,得改用 errors='strict' 加循环回退。另外 INSERT OR REPLACE 会重写整行,如果以后加了外键或触发器,行为会变,建议改成 ON CONFLICT(id) DO UPDATE。还有,API 返回的 publishedAt 是 UTC,我一开始直接按字符串排序,跨时区看数据会错位,后来统一存 ISO 格式再转本地时区。
现在库能查了,但中文 LIKE 在 2 万行上已经要 200ms 左右,分词搜索还没上。你们把评论落到本地之后,是直接上 FTS5,还是先做一层作者/视频的降维再搜?
0 条评论
还没有评论,写下第一条。