what's the pyhanlp
pyhanlp是HanLP的Python接口,支持自动下载与升级HanLP,兼容py2、py3。
安装
pip install pyhanlp
安装时可能遇到的问题:
- 报错:error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual
解决方法:手动下载,下载链接:https://pan.baidu.com/s/1WaBxFghTll6Zofz1DGOZBg
- 报错:jpype._jvmfinder.JVMNotFoundException: No JVM shared library file (jvm.dll) found. Try setting up the JAVA_HOME environment variable properly.
解决方法:HanLP主项目采用Java开发,所以需要Java运行环境,请安装JDK。需要保证JDK位数、操作系统位数和Python位数一致。pyhanlp在64位系统上通过了所有测试;在32位系统上可以运行但不做保证。
配置
默认在首次调用pyhanlp时自动下载jar包和数据包,并自动完成配置。
如果网速慢或者其他问题导致配置失败,需要自行下载data文件,然后放入pyhanlp文件的static目录中。下载地址:http://nlp.hankcs.com/download.php?file=data
如果还是失败,请参考https://github.com/hankcs/pyhanlp/wiki/手动配置
一、标准中文分词
使用命令hanlp segment进入交互分词模式,输入一个句子并回车,HanLP会输出分词结果:
$ hanlp segment 商品和服务 商品/n 和/cc 服务/vn 当下雨天地面积水分外严重 当/p 下雨天/n 地面/n 积水/n 分外/d 严重/a 龚学平等领导说,邓颖超生前杜绝超生 龚学平/nr 等/udeng 领导/n 说/v ,/w 邓颖超/nr 生前/t 杜绝/v 超生/vi
还可以重定向输入输出到文件等:
$ hanlp segment <<< '欢迎新老师生前来就餐' 欢迎/v 新/a 老/a 师生/n 前来/vi 就餐/vi
在Python中的实现
from pyhanlp import * print(HanLP.segment('你好,欢迎在Python中调用HanLP的API')) # [你好/vl, ,/w, 欢迎/v, 在/p, Python/nx, 中/f, 调用/v, HanLP/nx, 的/ude1, API/nx] ################### for term in HanLP.segment('下雨天地面积水'): print('{}\t{}'.format(term.word, term.nature)) # 获取单词与词性 ''' 下雨天 n 地面 n 积水 n ''' ################### testCases = [ "商品和服务", "结婚的和尚未结婚的确实在干扰分词啊", "买水果然后来世博园最后去世博会", "中国的首都是北京", "欢迎新老师生前来就餐", "工信处女干事每月经过下属科室都要亲口交代24口交换机等技术性器件的安装工作", "随着页游兴起到现在的页游繁盛,依赖于存档进行逻辑判断的设计减少了,但这块也不能完全忽略掉。"] for sentence in testCases: print(HanLP.segment(sentence)) ''' [商品/n, 和/cc, 服务/vn] [结婚/vi, 的/ude1, 和/cc, 尚未/d, 结婚/vi, 的/ude1, 确实/ad, 在/p, 干扰/vn, 分词/n, 啊/y] [买/v, 水果/n, 然后/c, 来/vf, 世博园/n, 最后/f, 去/vf, 世博会/n] [中国/ns, 的/ude1, 首都/n, 是/vshi, 北京/ns] [欢迎/v, 新/a, 老/a, 师生/n, 前来/vi, 就餐/vi] [工信处/n, 女干事/n, 每月/t, 经过/p, 下属/v, 科室/n, 都/d, 要/v, 亲口/d, 交代/v, 24/m, 口/n, 交换机/n, 等/udeng, 技术性/n, 器件/n, 的/ude1, 安装/v, 工作/vn] [随着/p, 页游/nz, 兴起/v, 到/v, 现在/t, 的/ude1, 页游/nz, 繁盛/a, ,/w, 依赖于/v, 存档/vi, 进行/vn, 逻辑/n, 判断/v, 的/ude1, 设计/vn, 减少/v, 了/ule, ,/w, 但/c, 这/rzv, 块/q, 也/d, 不能/v, 完全/ad, 忽略/v, 掉/v, 。/w] '''
说明
- HanLP中有一系列“开箱即用”的静态分词器,以Tokenizer结尾,在接下来的例子中会继续介绍。
- HanLP.segment其实是对StandardTokenizer.segmen的包装。
- 分词结果包含词性,每个词性的意思请查阅《HanLP词性标注集》。
算法详解
二、关键词提取、自动摘要
# 关键词提取 document = "水利部水资源司司长陈明忠9月29日在国务院新闻办举行的新闻发布会上透露," \ "根据刚刚完成了水资源管理制度的考核,有部分省接近了红线的指标," \ "有部分省超过红线的指标。对一些超过红线的地方,陈明忠表示,对一些取用水项目进行区域的限批," \ "严格地进行水资源论证和取水许可的批准。" print(HanLP.extractKeyword(document, 2)) # [水资源, 陈明忠] # 自动摘要 print(HanLP.extractSummary(document, 3)) # [严格地进行水资源论证和取水许可的批准, 水利部水资源司司长陈明忠9月29日在国务院新闻办举行的新闻发布会上透露, 有部分省超过红线的指标]
依存句法分析
命令为hanlp parse,同样支持交互模式和重定向:命令为hanlp parse,同样支持交互模式和重定向:
$ hanlp parse <<< '徐先生还具体帮助他确定了把画雄鹰、松鼠和麻雀作为主攻目标。' 1 徐先生 徐先生 nh nr _ 4 主谓关系 _ _ 2 还 还 d d _ 4 状中结构 _ _ 3 具体 具体 a a _ 4 状中结构 _ _ 4 帮助 帮助 v v _ 0 核心关系 _ _ 5 他 他 r rr _ 4 兼语 _ _ 6 确定 确定 v v _ 4 动宾关系 _ _ 7 了 了 u ule _ 6 右附加关系 _ _ 8 把 把 p pba _ 15 状中结构 _ _ 9 画 画 v v _ 8 介宾关系 _ _ 10 雄鹰 雄鹰 n n _ 9 动宾关系 _ _ 11 、 、 wp w _ 12 标点符号 _ _ 12 松鼠 松鼠 n n _ 10 并列关系 _ _ 13 和 和 c cc _ 14 左附加关系 _ _ 14 麻雀 麻雀 n n _ 10 并列关系 _ _ 15 作为 作为 p p _ 6 动宾关系 _ _ 16 主攻 主攻 v vn _ 17 定中关系 _ _ 17 目标 目标 n n _ 15 动宾关系 _ _ 18 。 。 wp w _ 4 标点符号 _ _
Python中实现
# 依存句法分析 print(HanLP.parseDependency("徐先生还具体帮助他确定了把画雄鹰、松鼠和麻雀作为主攻目标。")) ''' 1 徐先生 徐先生 nh nr _ 4 主谓关系 _ _ 2 还 还 d d _ 4 状中结构 _ _ 3 具体 具体 a ad _ 4 状中结构 _ _ 4 帮助 帮助 v v _ 0 核心关系 _ _ 5 他 他 r r _ 4 兼语 _ _ 6 确定 确定 v v _ 4 动宾关系 _ _ 7 了 了 u u _ 6 右附加关系 _ _ 8 把 把 p p _ 15 状中结构 _ _ 9 画 画 v v _ 8 介宾关系 _ _ 10 雄鹰 雄鹰 n n _ 9 动宾关系 _ _ 11 、 、 wp w _ 12 标点符号 _ _ 12 松鼠 松鼠 n n _ 10 并列关系 _ _ 13 和 和 c c _ 14 左附加关系 _ _ 14 麻雀 麻雀 n n _ 10 并列关系 _ _ 15 作为 作为 v v _ 6 动宾关系 _ _ 16 主攻 主攻 v vn _ 17 定中关系 _ _ 17 目标 目标 n n _ 15 动宾关系 _ _ 18 。 。 wp w _ 4 标点符号 _ _ '''
三、NLP分词
调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,这个类位于包名com.hankcs.hanlp.model.perceptron.PerceptronLexicalAnalyzer下,所以先用JClass得到类,然后就可以调用了:
PerceptronLexicalAnalyzer = JClass('com.hankcs.hanlp.model.perceptron.PerceptronLexicalAnalyzer') analyzer = PerceptronLexicalAnalyzer() print(analyzer.analyze("上海华安工业(集团)公司董事长谭旭光和秘书胡花蕊来到美国纽约现代艺术博物馆参观")) # [上海/ns 华安/nz 工业/n (/w 集团/n )/w 公司/n]/nt 董事长/n 谭旭光/nr 和/c 秘书/n 胡花蕊/nr 来到/v [美国纽约/ns 现代/ntc 艺术/n 博物馆/n]/ns 参观/v print(analyzer.analyze("我的希望是希望张晚霞的背影被晚霞映红").translateLabels()) # 我/代词 的/助词 希望/名动词 是/动词 希望/动词 张晚霞/人名 的/助词 背影/名词 被/介词 晚霞/名词 映红/动词 print(analyzer.analyze("支援臺灣正體香港繁體:微软公司於1975年由比爾·蓋茲和保羅·艾倫創立。")) # 支援/v 臺灣/ns 正體/n 香港/ns 繁體/n :/w 微软公司/ntc 於/p 1975年/t 由/p 比爾·蓋茲/nr 和/c 保羅·艾倫/nr 創立/v 。/w
说明
- NLP分词NLPTokenizer会执行词性标注和命名实体识别,由结构化感知机序列标注框架支撑。
- 默认模型训练自9970万字的大型综合语料库,是已知范围内全世界最大的中文分词语料库。语料库规模决定实际效果,面向生产环境的语料库应当在千万字量级。用户可以在自己的语料上训练新模型以适应新领域、识别新的命名实体。
四、索引分词
说明
- 调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,N最短路径的类位于包名com.hankcs.hanlp.tokenizer.IndexTokenizer下,先用JClass得到类,然后就可以调用了:
- 索引分词IndexTokenizer是面向搜索引擎的分词器,能够对长词全切分,另外通过term.offset可以获取单词在文本中的偏移量。
- 任何分词器都可以通过基类Segment的enableIndexMode方法激活索引模式。
# # -*- coding:utf-8 -*- from pyhanlp import * from jpype import * def demo_index_segment(): """ 索引分词 主副食品/n [0:4] 主副食/j [0:3] 副食品/n [1:4] 副食/n [1:3] 食品/n [2:4] 最细颗粒度切分: 主副食品/n [0:4] 主副食/j [0:3] 主/ag [0:1] 副食品/n [1:4] 副食/n [1:3] 副/b [1:2] 食品/n [2:4] 食/v [2:3] 品/ng [3:4] """ Term =JClass("com.hankcs.hanlp.seg.common.Term") IndexTokenizer = JClass("com.hankcs.hanlp.tokenizer.IndexTokenizer") term_list = IndexTokenizer.segment("主副食品") for term in term_list.iterator(): print("{} [{}:{}]".format(term, term.offset, term.offset + len(term.word))) print("最细颗粒度切分:") IndexTokenizer.SEGMENT.enableIndexMode(JInt(1)) # JInt用于区分重载 term_list = IndexTokenizer.segment("主副食品") for term in term_list.iterator(): print("{} [{}:{}]".format(term, term.offset, term.offset + len(term.word))) if __name__ == "__main__": demo_index_segment()
五、N-最短路径分词
说明
- 调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,N最短路径的类位于包名com.hankcs.hanlp.seg.NShort.NShortSegment下,最短路径的类位于包名com.hankcs.hanlp.seg.Viterbi.ViterbiSegment下,先用JClass得到类,然后就可以调用了
- N最短路分词器NShortSegment比最短路分词器慢,但是效果稍微好一些,对命名实体识别能力更强。
- 一般场景下最短路分词的精度已经足够,而且速度比N最短路分词器快几倍,请酌情选择。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_NShort_segment(sentences): """ N最短路径分词,该分词器比最短路分词器慢,但是效果稍微好一些,对命名实体识别能力更强 N-最短分词:[今天/t, ,/w, 刘志军/nr, 案/ng, 的/ude1, 关键/n, 人物/n, ,/w, 山西/ns, 女/b, 商人/nnt, 丁书苗/nr, 在/p, 市/n, 二/m, 中/f, 院/n, 出庭/vi, 受审/vi, 。/w] 最短路分词:[今天/t, ,/w, 刘志军/nr, 案/ng, 的/ude1, 关键/n, 人物/n, ,/w, 山西/ns, 女/b, 商人/nnt, 丁书苗/nr, 在/p, 市/n, 二/m, 中/f, 院/n, 出庭/vi, 受审/vi, 。/w] N-最短分词:[江西省监狱管理局/nt, 与/cc, 中国/ns, 太平洋/ns, 财产/n, 保险/n, 股份/n, 有限公司/nis, 南昌/ns, 中心支公司/nt, 保险/n, 合同/n, 纠纷案/nz] 最短路分词:[江西省监狱管理局/nt, 与/cc, 中国/ns, 太平洋/ns, 财产/n, 保险/n, 股份/n, 有限公司/nis, 南昌/ns, 中心支公司/nt, 保险/n, 合同/n, 纠纷案/nz] N-最短分词:[新北商贸有限公司/nt] 最短路分词:[新北商贸有限公司/nt] """ NShortSegment = JClass("com.hankcs.hanlp.seg.NShort.NShortSegment") Segment = JClass("com.hankcs.hanlp.seg.Segment") ViterbiSegment = JClass("com.hankcs.hanlp.seg.Viterbi.ViterbiSegment") nshort_segment = NShortSegment().enableCustomDictionary(False).enablePlaceRecognize( True).enableOrganizationRecognize(True) shortest_segment = ViterbiSegment().enableCustomDictionary( False).enablePlaceRecognize(True).enableOrganizationRecognize(True) for sentence in sentences: print("N-最短分词:{} \n最短路分词:{}".format( nshort_segment.seg(sentence), shortest_segment.seg(sentence))) if __name__ == "__main__": sentences = [ "今天,刘志军案的关键人物,山西女商人丁书苗在市二中院出庭受审。", "江西省监狱管理局与中国太平洋财产保险股份有限公司南昌中心支公司保险合同纠纷案", "新北商贸有限公司", ] demo_NShort_segment(sentences)
六、CRF分词
说明
- 调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,N最短路径的类位于包名com.hankcs.hanlp.model.crf.CRFLexicalAnalyzer下,先用JClass得到类,然后就可以调用了
- CRF对新词有很好的识别能力,但是开销较大。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_CRF_lexical_analyzer(tests): """ CRF词法分析器 商品/n 和/c 服务/vn [上海/ns 华安/nz 工业/n (/n 集团/n )/v 公司/n]/nt 董事长/n 谭旭光/nr 和/c 秘书/n 胡花蕊/nr 来到/v [美国/ns 纽约/ns 现代/t 艺术/n 博物馆/n]/ns 参观/v [微软/nt 公司/n]/nt 於/p 1975年/t 由/p 比爾·蓋茲/n 和/c 保羅·艾倫/v 創立/v ,/v 18年/n 啟動/v 以/p 智慧/n 雲端/n 、/v 前端/n 為/v 導向/n 的/u 大/a 改組/vn 。/w """ CRFLexicalAnalyzer = JClass("com.hankcs.hanlp.model.crf.CRFLexicalAnalyzer") analyzer = CRFLexicalAnalyzer() for sentence in tests: print(analyzer.analyze(sentence)) if __name__ == "__main__": sentences = ["商品和服务", "上海华安工业(集团)公司董事长谭旭光和秘书胡花蕊来到美国纽约现代艺术博物馆参观", "微软公司於1975年由比爾·蓋茲和保羅·艾倫創立,18年啟動以智慧雲端、前端為導向的大改組。" ] demo_CRF_lexical_analyzer(sentences)
七、极速词典分词
说明
- 调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,N最短路径的类位于包名com.hankcs.hanlp.tokenizer.SpeedTokenizer下,先用JClass得到类,然后就可以调用了
- 极速分词是词典最长分词,速度极其快,精度一般。
- 在i7-6700K上跑出了4500万字每秒的速度。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * import time def demo_high_speed_segment(): """ 演示极速分词,基于DoubleArrayTrie实现的词典正向最长分词,适用于“高吞吐量”“精度一般”的场合 [江西, 鄱阳湖, 干枯, ,, 中国, 最大, 淡水湖, 变成, 大草原] SpeedTokenizer分词速度:1253607.32字每秒 """ SpeedTokenizer = JClass("com.hankcs.hanlp.tokenizer.SpeedTokenizer") text = "江西鄱阳湖干枯,中国最大淡水湖变成大草原" JClass("com.hankcs.hanlp.HanLP$Config").ShowTermNature = False print(SpeedTokenizer.segment(text)) start = time.time() pressure = 1000000 for i in range(pressure): SpeedTokenizer.segment(text) cost_time = time.time() - start print("SpeedTokenizer分词速度:%.2f字每秒" % (len(text) * pressure / cost_time)) if __name__ == "__main__": demo_high_speed_segment()
服务器
通过hanlp serve来启动内置的http服务器,默认本地访问地址为:http://localhost:8765 ;也可以访问官网演示页面:http://hanlp.hankcs.com/ 。
与其他项目共享data
HanLP具备高度可自定义的特点,所有模型和词典都可以自由替换。如果你希望与别的项目共享同一套data,只需将该项目的配置文件hanlp.properties拷贝到pyhanlp的安装目录下即可。本机安装目录可以通过hanlp --version获取。
同时,还可以通过--config临时加载另一个配置文件:
hanlp segment --config path/to/another/hanlp.properties
参考:https://github.com/hankcs/pyhanlp
com.hankcs.hanlp.tokenizer.SpeedTokenizer