ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

ECDICT 实战指南:一份开源英汉词典数据库,填平背单词应用的三个数据坑

ECDICT 实战指南:一份开源英汉词典数据库,填平背单词应用的三个数据坑

ECDICT 实战指南:一份开源英汉词典数据库,填平背单词应用的三个数据坑

深夜两点,你在调试阅读器里的划词翻译,输入框里躺着gave这个单词,词典却返回一片空白。不是你数据收得少,而是大多数词典数据只收录原型词。ECDICT 是一个免费开源的英汉词典数据库,基础版本收录了 76 万条词,真正值钱的地方在于,它把词形变化、双重词频、词性比例这些"元数据"做成了标准字段,让开发者少踩三个典型的大坑。

坑一:词典收齐了单词,却漏掉了它的形态

刚才那个场景里,gave查不到,是因为大部分词库只收录 give、take 这种原型。以往你只能自己写规则把gave猜回 give,猜错了又是一轮白费。ECDICT 换了个做法:把动词的时态变体也作为独立词条收录进库,同时用exchange字段记录 8 类变化——过去式p、过去分词d、现在分词i、第三人称单数3、比较级r、最高级t、复数s,外加原型0。

from stardict import DictCsv d = DictCsv('ecdict.csv') print(d.query('gave')['translation']) # 直接命中释义,无需猜词

换个说法,exchange就是附在每条词上的微型词形数据库,既能正向查"give 的过去式是什么",也能反向问"perceived 的原型是谁"。做 Anki 卡片、背单词应用时,这一条字段能帮你省掉一整套路标推导代码。

坑二:单词值不值得背,两个词频字段说了算

解决了"查不查得到",更现实的问题来了:查到了,怎么判断它值不值得背?你的应用要给用户推荐生词,总得知道排在 9000 名的词和排在 9 万名之后的词,优先级差多远。ECDICT 为每个词同时标注bnc和frq两个词频顺序:bnc统计几百年来的英国文献,偏传统;frq统计最近 20 年的当代语料,偏现代。

单词bnc(传统词频)frq(当代词频)
quay(码头)8906两万名开外
Taliban未进前 20 万6089

quay 在百年文献里是高频率词,因为当年航海是主流交通;Taliban 在当代语料里冒到了 6000 多名,传统词频却查无此词。想看懂 19 世纪名著,按bnc排序背;想啃现代科技文章,按frq排序背。这两个字段直接当推荐权重用,省得你自己重新统计一遍语料。

坑三:词干还原别靠猜,查表才可靠

对单次查询来说,词频已经够用了,可一旦涉及整篇文档,问题又来了。统计文档词频时,gave、taken、teeth如果不还原成原型,就会变成三个互不相干的 token。靠判断-ed、-ing结尾的规则算法,遇到不规则变化就翻车。ECDICT 作者扫描了 BNC 全部一亿条语料,生成了lemma.en.txt,包含 8 万多个词干组、18 万多条单词。

from stardict import LemmaDB db = LemmaDB(); db.load('lemma.en.txt') print(db.word_stem('teeth')) # 反向找原型,得到 tooth print(db.get('take')) # 正向列出全部变体

查询永远比猜测可靠——这是整个项目最值得带走的工程理念,拼写检查领域的权威库 hunspell 也是这么干的。

工程上的推荐做法是"先查表,查不到再用规则兜底",能覆盖 95% 以上的情况。

一个反直觉的选择:仓库里为什么只放 CSV

这些能力都建立在同一个前提上:你得先把数据用起来,而这就绕不开一个反直觉的选择。拿到仓库你会发现,主仓库只放 CSV,不直接给 SQLite。原因很简单:CSV 是纯文本,贡献者提交 PR、对比 diff 都方便。但本地开发时,76 万行的 CSV 加载偏慢,作者建议日常转换成 SQLite。更省心的是,stardict.py里的 DictCsv、StarDict、DictMySQL 三个类接口完全一致——query、match、query_batch、register、update、remove、commit一字不差,换存储后端不用改业务代码,完整版数据则打包在stardict.7z里。

查不到单词时,先看看 sw 字段

把数据跑起来之后,你还会撞上一个高频率场景:用户输入不标准。你可能遇到过,输入 long-time 查不到,但词典里明明有 longtime。ECDICT 为每个词维护了隐藏字段sw(strip-word),规则是删掉字符串里所有非字母数字的字符、再转成小写。匹配按sw走,long-time、long time、longtime 就能互相命中。这背后其实是单词的自然演变:先是一个词组,再是连字符组合,用得多了连字符也省了。很多商业词典没有这个字段,用户输入形态不对就查不出来,而这里可以。

两个顺手彩蛋:词性比例与词根词缀

除了这三大坑,项目里还藏着两个能直接拿来用的彩蛋。pos字段记录了词性比例,比如 fuse 是n:46/v:54,表示它在语料库里 46% 的时候是名词、54% 的时候是动词。这个比例可以直接决定释义的展示顺序,翻译接口也能据此优先选择更常见的词性。另外,wordroot.txt是 JSON 格式的词根词缀资料(含近义词、反义词、例句与词源),resemble.txt是形近词表,给背单词应用做"形近词辨析"和词根联想记忆,都是现成素材。

现在就能动手的验证

回到那个深夜场景,方案已经很清晰了:克隆仓库,跑一个最小验证,一个小时内让问题落地。

git clone https://gitcode.com/gh_mirrors/ec/ECDICT

先把 76 万条 CSV 转成本地 SQLite,再查一下gave:

from stardict import convert_dict, StarDict convert_dict('ecdict.db', 'ecdict.csv') # 一次性转换 print(StarDict('ecdict.db').query('gave')) # 毫秒级命中

自此,你的阅读器不会再对 gave 翻白眼,你的背单词应用也有了可靠的词频与词形数据。这份免费开源的英汉词典数据库值得放进你的下一个语言工具里,动手试试吧。

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

RELATED READING

延伸阅读

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