如何使jieba自定义词典持久化

jieba分词是利用python进行自然语言处理中必不可少的常用工具,添加自定义词典也是jieba分词中的的常用功能。

然而每次运行程序,jieba自定义词典都需要重新加载,添加的自定义词典只对当前程序生效。如果自定义词典的数量比较巨大(百万级及以上),每次重新加载这一步将会耗费很长的时间。

网上找不到相关的持久化解决方案,只会告诉你如何使用jieba.load_userdict,所以我的这个完整的持久化方案也算是全网首发了。

事先准备好自定义词典:

创建一个txt文件,然后写入你的分词,一个词占一行;每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。类似于如下形式:

沈孟良 360 nr
富民理财睿盈 360 nfp
广发多添富 360 nfp

方案分析:

  • 整体的解决方案是将加载了自定义词典的jieba模型存储到本地,每次不用再次加载词典而是直接调用模型。每次启动jieba都可以看到会输出以下信息,说明jieba还是会从缓存中读取一些信息的。
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
Loading model cost 0.474 seconds.
Prefix dict has been built succesfully.
  • 可以明确的一点是,我们要查看并修改部分的jieba源码,因为目前的jieba功能不能完全满足我们的需求,所以,把jieba项目clone到本地:
git clone https://github.com/fxsjy/jieba.git

为了防止和系统中已安装的jieba重名,可以把这个文件重命名为jieba_local

  • jieba源码中已经定义了一个dict.txt,存放jieba分词的词典,这个词典在init.py的第350行的get_dict_file函数中被调用。而从下面的代码中,我们看到了熟悉的’Loading model from cache‘,另外,可以看出,调用词典的前提是 load_from_cache_fail。
 load_from_cache_fail = True
            if os.path.isfile(cache_file) and (abs_path == DEFAULT_DICT or
                os.path.getmtime(cache_file) > os.path.getmtime(abs_path)):
                default_logger.debug(
                    "Loading model from cache %s" % cache_file)
                try:
                    with open(cache_file, 'rb') as cf:
                        self.FREQ, self.total = marshal.load(cf)
                    load_from_cache_fail = False
                except Exception:
                    load_from_cache_fail = True

            if load_from_cache_fail:
                wlock = DICT_WRITING.get(abs_path, threading.RLock())
                DICT_WRITING[abs_path] = wlock
                with wlock:
                    self.FREQ, self.total = self.gen_pfdict(self.get_dict_file())
                    default_logger.debug(
                        "Dumping model to file cache %s" % cache_file)
                    try:
                        # prevent moving across different filesystems
                        fd, fpath = tempfile.mkstemp(dir=tmpdir)
                        with os.fdopen(fd, 'wb') as temp_cache_file:
                            marshal.dump(
                                (self.FREQ, self.total), temp_cache_file)
                        _replace_file(fpath, cache_file)
                    except Exception:
                        default_logger.exception("Dump cache file failed.")

                try:
                    del DICT_WRITING[abs_path]
                except KeyError:
                    pass

所以要把我们的自定义词典添加到dict.txt中,并且让之后的每次都成功调用缓存文件,就不会再次加载词典了。Nice!

  • jieba的github里面的Readme.txt中给出了:
更改分词器(默认为 jieba.dt)的 tmp_dir 和 cache_file 属性,可分别指定缓存文件所在的文件夹及其文件名,用于受限的文件系统。

这样我们就可以指定jieba缓存的文件夹的文件名了。

方案实施

分析了修改的思路和原理,下面开始实施方案:

  • 首先把所有的自定义词典复制,粘贴到jieba_local中的dict.txt文件夹内
  • 接着,另外new一个.py文件,随意命名,写入
import jieba_local

jieba_local.dt.tmp_dir = './'
jieba_local.dt.cache_file = 'jieba.temp'
for i in jieba_local.cut('恭喜FPX夺冠啦啦啦啦'):
    print(i)
  • 运行该代码之后,加载了新的词典,本地文件夹下应该已经生成了名为jieba.temp的缓存文件
  • 以后再次运行只需把jieba_local拷贝到项目中,在调用的程序中指定缓存文件的文件夹和路径即可:
jieba_local.dt.tmp_dir = './'
jieba_local.dt.cache_file = 'jieba.temp'
  • 可以看到指定路径过后能成功导入缓存模型。模型本身占用比较大的存储空间(我的将近1G),另外加载的速度也比之前要慢,用了28秒多的时间,但是无需再次加载自定义词典,相比于之前的40多秒的加载自定义词典的时间还是缩短了将近一半,算是用空间换时间的方法。
Building prefix dict from the default dictionary ...
Loading model from cache ./jieba.temp
Loading model cost 28.665 seconds.
Prefix dict has been built succesfully.

\color{red}{(涉及公司机密,完整代码和数据无法提供,请见谅,纯原创,转载请注明来源)}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容