ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

meikipop词典系统深度解析:如何用JMdict与Kanjidic构建毫秒级查询的dictionary.pkl

meikipop词典系统深度解析:如何用JMdict与Kanjidic构建毫秒级查询的dictionary.pkl

【免费下载链接】meikipop

meikipop - universal japanese ocr popup dictionary for windows, linux and macos

项目地址:https://gitcode.com/gh_mirrors/me/meikipop
点击查看免费下载

meikipop 是一款跨平台的日语 OCR 弹出式词典(universal japanese ocr popup dictionary),支持 Windows、Linux 和 macOS。本文带你深度解析它的词典系统:如何将权威的 JMdict 词库与 Kanjidic 汉字数据离线预处理成单个dictionary.pkl文件,从而实现毫秒级的屏幕查词体验。

为什么需要预处理:从"字典"到"高速索引"

🤔 一个朴素的疑问:屏幕上的 OCR 结果每 10ms 就可能刷新一次,如果每次都去解析几 MB 的 XML 词典,查询必然卡顿。

meikipop 的答案是一次性预处理:把原始词典源文件(XML、CSV)在构建期彻底"消化"成内存友好的数据结构,运行时只需一次pickle.load()即可加载全部数据。核心思路是:

  • 构建期(慢,只跑一次):下载 JMdict、Kanjidic 等源文件,解析、清洗、交叉索引
  • 运行期(快,每次查词):内存字典直接查表 + 反变形 + 缓存

这样,查词的热路径上几乎没有 I/O 和 XML 解析开销——这就是"毫秒级"的来源。

四大数据源:dictionary.pkl 的血统

构建脚本 build_dictionary.py 定义了 4 个原始数据源,下载后缓存在本地,重复构建无需再次下载:

数据源作用贡献给 pkl 的内容
JMdict_eEDRDG 项目的权威日语词库(XML)词条释义、读写形式、词性标签
kanjidic2汉字辞典(XML)每个汉字的含义、音读/训读
CHISE IDS汉字部件顺序表汉字分解部件(components)
jiten.moe 频率表词频 CSV每个词条的频次排名,用于排序

此外还有一个"隐藏数据源":随程序分发的变形规则文件 deconjugator.json,它定义了动词/形容词等词形变化的还原规则,同样会被打包进dictionary.pkl。

一键构建:meikipop build-dict

如果你只想更新词典,不需要理解任何源码:

meikipop build-dict

这条命令在 main.py 中注册为build-dict子命令,内部按 5 个阶段执行(见 build_dictionary.py 的 main()):

  1. 加载源文件—— 优先读缓存,缺失则下载并落盘
  2. 解析词频表—— 构建{(词, 读法): 排名}映射
  3. 解析 JMdict_e—— 解压 gzip、解析 XML 实体,生成词条与查找表
  4. 构建 Kanjidic 数据—— 汉字含义、部件分解、加权读音与例句
  5. 序列化保存—— 以最高压缩协议pickle.dump写出dictionary.pkl

构建完成后会打印类似信息:

[3/5] Parsing JMdict_e ... 98xxx core entries | xxxx lookup refs [5/5] Saving dictionary to .../dictionary.pkl ... Saved xx.x MB in x.xs

解剖 dictionary.pkl:4 个核心字段

无论走 JMdict 构建还是 Yomitan 导入,最终产出的都是同一个 payload 结构(build_dictionary.py):

字段类型说明
entries{entry_id: [sense, ...]}核心词条表,每个 sense 含glosses(释义)、pos(词性)、tags
lookup_map{表记: [(written, reading, freq, entry_id)]}高速查找表:以"表面形式"为键,同时覆盖汉字键(keb)与假名键(reb)两条查询路径
kanji_entries{character: {...}}汉字条目:含义、读音、部件分解、高频例句
deconjugator_ruleslist[dict]词形还原规则,运行时由 Deconjugator 消费

其中lookup_map是性能的关键:查询桜或さくら都是一次哈希表dict.get(),O(1) 拿到候选词条列表(customdict.py)。

JMdict 解析的精细处理(build_jmdict_data)值得一提:

  • 严格区分sK/sk(search-only)等形式标记,选出规范显示形式(canonical form)
  • 按stagk/stagr把同一个 JMdict 条目拆分成多个合成子条目(synthetic ID 从10_000_000起编号),保证每个表记只匹配到适用释义
  • 词频查不到时回退到DEFAULT_FREQ = 999_999,保证排序稳定

运行期查询:Lookup 线程如何做到毫秒级响应

词典加载后,真正的性能魔法发生在查询线程 lookup.py。它的lookup()流程:

  1. 截断与截词:超过max_lookup_length截断,遇到、。「」等日文标点即截断(JAPANESE_SEPARATORS)
  2. LRU 缓存命中即返回:最多保留 500 条结果的OrderedDict缓存,鼠标扫过的区域反复查询几乎零成本
  3. 前缀扫描:从最长前缀开始逐个变短,每个前缀先交给Deconjugator 反变形(如食べた→食べる),再查lookup_map
  4. 平假名/片假名回退:查不到时自动做hira↔kata换算重试(_get_map_entries)
  5. 优先级排序:匹配长度 + 对数词频 + 假名加成 − 变形步数惩罚,合并同 (written, reading) 的同义重复项,最终只保留前MAX_DICT_ENTRIES = 10条(config.py)

📌 反变形引擎本身是一个基于规则的 BFS 状态机:每条规则形如{dec_end, con_end, dec_tag, con_tag}(例如把词尾け还原为く并打上v5k标签),最多迭代 10 轮防止爆炸,见 deconjugator.py。查询端还会做词性校验——变形规则声明了v5k等词性标签,词典条目的 sense 中必须包含对应词性,否则该结果被剪枝(lookup.py),大幅减少误报。

汉字条目:Kanjidic + IDS + 词频三合一

当查询结果的首字符是汉字时,Lookup 会额外附上一条汉字卡(lookup.py)。这张卡的生成是构建期最复杂的步骤 build_kanjidic_data:

  • 含义:直接取 kanjidic2 中默认语言的meaning
  • 读音:不是简单照搬,而是把 JMdict 中真实含该汉字的词当作语料,用词频加权投票——一个词的排名越靠前,它对"这个汉字在这里读 X"的背书权重越高;优先级标签(ichi2、news1等)还有 10 倍加成
  • 部件:从 CHISE IDS 中取日语部件序列(优先[J]/[JA]标记的列),再逐个部件映射回 kanjidic 含义
  • 例句:按加权分数选出 3 个最可靠读音,每个读音配一个高频真实词例

这样弹出的汉字卡里的读音和例句,都是"有真实语料背书"的,而非辞典照抄。

词典放在哪里 & 如何更新

dictionary.pkl由 paths.py 统一管理,位置按平台区分:

  • Windows:%LOCALAPPDATA%\meikipop\dictionary.pkl
  • Linux:~/.config/meikipop/dictionary.pkl(数据目录)
  • macOS:~/Library/Application Support/meikipop/dictionary.pkl

加载逻辑在 Dictionary.load_dictionary:文件缺失时会自动下载官方预制词典(zip 中的dictionary.pkl)并重试加载;加载后还会按文件修改时间只校验一次结构完整性(4 元组字段、entry_id 可达性等),校验结果缓存进config.ini,避免每次启动全量扫描。

想用自己的词库?导入 Yomitan 词典

如果你偏好 Yomitan/Yomichan 的社区词典,meikipop 提供了两条导入命令(注册于 main.py):

# 尽量保留原始格式(HTML) meikipop import-yomitan-dict-html my_dict.zip # 生成紧凑的纯文本词典,可一次导入多个 meikipop import-yomitan-dict-text dict1.zip dict2.zip

导入脚本 import_yomitan_dict_text.py 的产物与 JMdict 构建格式完全一致:同样生成entries+lookup_map(汉字路径 + 假名路径双表),并用ID_NAMESPACE = 10_000_000对多词典的 entry_id 做命名空间隔离防止冲突。需要注意的是:导入会覆盖默认词典,且 Yomitan 词典不产生kanji_entries(汉字卡会缺失)。

小结:为什么这套架构值得借鉴 ⚡

  • 构建期/运行期彻底分离:所有重型解析(XML 实体、gzip、词频交叉)只发生在build-dict,运行期是一次pickle.load起步
  • 双路径查找表:lookup_map同时以汉字表记和假名读法为键,让"看汉字查词"与"看假名查词"共用同一份数据
  • 规则式反变形 + 词性剪枝:以极低的运行时成本覆盖了日语变形的长尾
  • 缓存与截断:LRU 结果缓存 + 长度/标点截断,让高频查询路径接近零开销
  • 单一事实来源:dictionary.pkl一份文件承载词条、查找表、汉字卡、变形规则,分发、备份、更新都是一件事

如果你想深入源码,建议按这条主线阅读:build_dictionary.py(数据怎么来)→ customdict.py(数据长什么样)→ deconjugator.py(变形引擎)→ lookup.py(查询如何跑)。理解完这四块,你就掌握了 meikipop 毫秒级查词的完整链路。

【免费下载链接】meikipop

meikipop - universal japanese ocr popup dictionary for windows, linux and macos

项目地址:https://gitcode.com/gh_mirrors/me/meikipop
点击查看免费下载

相关推荐

上一篇:3 步搞定百度网盘秒传链接:文件不用动,链接不过期
下一篇:LayerDivider:开源免费的图片转PSD分层工具,一张图变可编辑图层

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进