python怎么使⽤⾃定义停⽤词_pyhanlp停⽤词与⽤户⾃定义词
典功能详解
hanlp的词典模式
python转java代码之前我们看了hanlp的词性标注,现在我们就要使⽤⾃定义词典与停⽤词功能了,⾸先关于HanLP的词性标注⽅式具体请看HanLP词性标注集。
其核⼼词典形式如下:
⾃定义词典
⾃定义词典有多种添加模式,⾸先是展⽰的⼀个⼩例⼦,展⽰了词汇的动态增加与强⾏插⼊,删除等。更复杂的内容请参考后边的第⼆段代码。
简单的例⼦
from pyhanlp import *
text = "攻城狮逆袭单⾝狗,迎娶⽩富美,⾛上⼈⽣巅峰"  #怎么可能噗哈哈!
print(HanLP.segment(text))
CustomDictionary = JClass("com.hankcs.hanlp.dictionary.CustomDictionary")
CustomDictionary.add("攻城狮")  #动态增加
CustomDictionary.insert("⽩富美", "nz 1024")  #强⾏插⼊
#ve("攻城狮"); #删除词语(注释掉试试)
CustomDictionary.add("单⾝狗", "nz 1024 n 1")
# 展⽰该单词词典中的词频统计 展⽰分词
("单⾝狗"))
print(HanLP.segment(text))
# 增加⽤户词典,对其他分词器同样有效
# 注意此处,CRF分词器将单⾝狗分为了n即使单⾝狗:"nz 1024 n 1"
CRFnewSegment = wSegment("crf")
print(CRFnewSegment.seg(text))
[攻城狮,逆袭,单⾝狗,,,迎娶,⽩富美,,,⾛上,⼈⽣,巅峰]
nz 1024 n 1
[攻城狮,逆袭,单⾝狗,,,迎娶,⽩富美,,,⾛上,⼈⽣,巅峰]
[攻城,狮逆袭,单⾝狗,,,迎娶,⽩富美,,,⾛,上,⼈⽣,巅峰]
复杂的例⼦
""" 演⽰⾃定义词性,以及往词典中插⼊⾃定义词性的词语
由于采⽤了反射技术,⽤户需对本地环境的兼容性和稳定性负责
TO-DO
如果使⽤了动态词性之后任何类使⽤了switch(nature)语句,必须注册每个类
"""
# 对于系统中已有的词性,可以直接获取
Nature = JClass("com.pus.tag.Nature")
pc_nature = Nature.fromString("n")
print(pc_nature)
# 此时系统中没有"电脑品牌"这个词性
pc_nature = Nature.fromString("电脑品牌")
print(pc_nature)
# 我们可以动态添加⼀个
pc_nature = ate("电脑品牌");
print(pc_nature)
# 可以将它赋予到某个词语
LexiconUtility = JClass("com.hankcs.hanlp.utility.LexiconUtility")
LexiconUtility.setAttribute("苹果电脑", pc_nature)
# 或者
LexiconUtility.setAttribute("苹果电脑", "电脑品牌1000")
# 它们将在分词结果中⽣效
term_list = HanLP.segment("苹果电脑可以运⾏开源阿尔法狗代码吗")
print(term_list)
for term in term_list:
if term.nature == pc_nature:
print("到了[{}] : {}\n".format(pc_nature, term.word))
# 还可以直接插⼊到⽤户词典
CustomDictionary = JClass("com.hankcs.hanlp.dictionary.CustomDictionary") CustomDictionary.insert("阿尔法狗", "科技名词1024")
StandardTokenizer = JClass("com.kenizer.StandardTokenizer") ablePartOfSpeechTagging(True)  # 依然⽀持隐马词性标注term_list = HanLP.segment("苹果电脑可以运⾏开源阿尔法狗代码吗")
print(term_list)
n
None
电脑品牌
[苹果电脑/电脑品牌,可以/v,运⾏/vn,开源/v,阿尔法/nrf,狗/n,代码/n,吗/y]
到了 [电脑品牌] :苹果电脑
[苹果电脑/电脑品牌,可以/v,运⾏/vn,开源/v,阿尔法狗/科技名词,代码/n,吗/y]
关于⾃定义词典的说明(原作者的原⽂)
说明
l CustomDictionary是⼀份全局的⽤户⾃定义词典,可以随时增删,影响全部分词器。另外可以在任何分词器中关闭它。通过代码动态增删不会保存到词典⽂件。
l 中⽂分词≠词典,词典⽆法解决中⽂分词,Segment提供⾼低优先级应对不同场景,请参考FAQ。
追加词典
l CustomDictionary主词典⽂本路径是data/dictionary/,⽤户可以在此增加⾃⼰的词语(不推荐);也可以单独新建⼀个⽂本⽂件,通过配置⽂件CustomDictionaryPath=data/dictionary/;我的词典.txt;来追加词典(推荐)。
l 始终建议将相同词性的词语放到同⼀个词典⽂件⾥,便于维护和分享。
词典格式
l 每⼀⾏代表⼀个单词,格式遵从[单词] [词性A] [A的频次] [词性B] [B的频次] ...如果不填词性则表⽰采⽤词典的默认词性。
l 词典的默认词性默认是名词n,可以通过配置⽂件修改:全国地名⼤全.txt ns;如果词典路径后⾯空格紧接着词性,则该词典默认是该词性。
l 在统计分词中,并不保证⾃定义词典中的词⼀定被切分出来。⽤户可在理解后果的情况下通过
Segment#enableCustomDictionaryForcing强制⽣效。
l 关于⽤户词典的更多信息请参考词典说明⼀章(请看本⽂最后)。
停⽤词
关于停⽤词,我同样先给出了⼀个简单的例⼦,你可以使⽤这个例⼦来完成你所需要的功能。要注意的⼀点是,因为java中的类所返回的数据类型与Python不统⼀,所以当你使⽤不同的函数的时候,⼀定要先检查输出结果在Python中的类型,不然可能会出现意想不到的问题。
假如你想了解更多,可以看第⼆个更复杂的例⼦。
简单的例⼦
# 使⽤停⽤词的简单例⼦
text = "⼩区居民有的反对喂养流浪猫"
CRFnewSegment = wSegment("crf")
term_list = CRFnewSegment.seg(text)
# BasicTokenizer = SafeJClass("com.kenizer.BasicTokenizer")
# term_list = BasicTokenizer.segment(text)
CoreStopWordDictionary = JClass("com.hankcs.hanlp.dictionary.stopword.CoreStopWordDictionary")
CoreStopWordDictionary.apply(term_list)
HanLP.Config.ShowTermNature = False
print(term_list)
print([i.word for i in term_list])
[⼩区,居民,反对,养,流,浪,猫]
['⼩区', '居民', '反对', '养', '流', '浪', '猫']
复杂的例⼦
# 停⽤词
# 在import pyhanlp之前编译⾃⼰的Java class,并放⼊pyhanlp/static中
import os
from pyhanlp.static import STATIC_ROOT, HANLP_JAR_PATH
java_code_path = os.path.join(STATIC_ROOT, 'MyFilter.java')
with open(java_code_path, 'w') as out:
java_code = """
import com.hankcs.hanlp.dictionary.stopword.CoreStopWordDictionary;
import com.hankcs.hanlp.dictionary.stopword.Filter;
import com.hankcs.hanlp.segmon.Term;
public class MyFilter implements Filter
{
public boolean shouldInclude(Term term)
{
if (term.nature.startsWith('m')) return true; // 数词保留
return !ains(term.word); // 停⽤词过滤
}
}
"""
out.write(java_code)
os.system('javac -cp {} {} -d {}'.format(HANLP_JAR_PATH, java_code_path, STATIC_ROOT))
# 编译结束才可以启动hanlp
CoreStopWordDictionary = JClass("com.hankcs.hanlp.dictionary.stopword.CoreStopWordDictionary") Filter = JClass("com.hankcs.hanlp.dictionary.stopword.Filter")
Term = JClass("com.hankcs.hanlp.segmon.Term")
BasicTokenizer = JClass("com.kenizer.BasicTokenizer")
NotionalTokenizer = JClass("com.kenizer.NotionalTokenizer")
text = "⼩区居民有的反对喂养流浪猫,⽽有的居民却赞成喂养这些⼩宝贝"
# 可以动态修改停⽤词词典
CoreStopWordDictionary.add("居民")
print(NotionalTokenizer.segment(text))
print(NotionalTokenizer.segment(text))
# 可以对任意分词器的结果执⾏过滤
term_list = BasicTokenizer.segment(text)
print(term_list)
CoreStopWordDictionary.apply(term_list)
print(term_list)
# 还可以⾃定义过滤逻辑
MyFilter = JClass('MyFilter')
CoreStopWordDictionary.FILTER = MyFilter()
print(NotionalTokenizer.segment("数字123的保留"))  #“的”位于所以被过滤,数字得到保留
[⼩区/n,反对/v,喂养/v,流浪猫/nz,赞成/v,喂养/v,⼩宝贝/nz]
[⼩区/n,居民/n,反对/v,喂养/v,流浪猫/nz,居民/n,赞成/v,喂养/v,⼩宝贝/nz]
[⼩区/n,居民/n,有/vyou,的/ude1,反对/v,喂养/v,流浪猫/nz,,/w,⽽/cc,有的/rz,居民/n,却/d,赞成/v,喂养/v,这些/rz,⼩宝贝/nz]
[⼩区/n,居民/n,反对/v,喂养/v,流浪猫/nz,居民/n,赞成/v,喂养/v,⼩宝贝/nz]
[数字/n, 123/m,保留/v]
词典说明(原作者原⽂)
本章详细介绍HanLP中的词典格式,满⾜⽤户⾃定义的需要。HanLP中有许多词典,它们的格式都是相似的,形式都是⽂本⽂档,随时可以修改。
基本格式
词典分为词频词性词典和词频词典。
词频词性词典(如)
l 每⼀⾏代表⼀个单词,格式遵从[单词] [词性A] [A的频次] [词性B] [B的频次] ...。
l ⽀持省略词性和频次,直接⼀⾏⼀个单词。
l .txt词典⽂件的分隔符为空格或制表符,所以不⽀持含有空格的词语。如果需要⽀持空格,请使⽤英⽂逗号,分割的纯⽂本.csv⽂件。在使⽤Excel等富⽂本编辑器时,则请注意保存为纯⽂本形式。
词频词典(如)
l 每⼀⾏代表⼀个单词或条⽬,格式遵从[单词] [单词的频次]。
l 每⼀⾏的分隔符为空格或制表符。
少数词典有⾃⼰的专⽤格式,⽐如同义词词典兼容《同义词词林扩展版》的⽂本格式,⽽转移矩阵词典则是⼀个csv表格。
下⽂主要介绍通⽤词典,如不注明,词典特指通⽤词典。
数据结构
Trie树(字典树)是HanLP中使⽤最多的数据结构,为此,我实现了通⽤的Trie树,⽀持泛型、遍历、储存、载⼊。
⽤户⾃定义词典采⽤AhoCorasickDoubleArrayTrie和⼆分Trie树储存,其他词典采⽤基于双数组Trie树(DoubleArrayTrie)实现的AC⾃动机AhoCorasickDoubleArrayTrie。关于⼀些常⽤数据结构的性能评估,请参考wiki。
储存形式
词典有两个形态:⽂本⽂件()和缓存⽂件(bin或ie.dat和ie.value)。