【中文分词】基于ICTCLAS的Python中文分词

本文介绍了一次使用ICTCLAS进行中文分词的实际操作过程。从安装配置到使用Python实现分词与词性标注,分享了具体的代码示例及分词效果。

前言

在ICT实习获得的第一个任务与中文分词有关,本想用Stanford中文分词器,苦于VirtualBox中的Ubuntu跑Stanford的中文分词程序的时候会出现OSError: Java Command Failed 的错误。负责OS这方面的队友在纠结不前之时,老师提醒了我:为什么不去试试别的分词器呢?

网上搜索了一下中文分词,一眼看到这个ICTCLAS,哈哈哈我正在这里实习为何不试试看呢?

优快云上花了不少积分,PUDN上也花了不少积分,下载开发文档和看配置blog也花了不少时间……大家得出的结论似乎都是“难配”,“错误多”,“不知道什么问题”……

我也几乎把这些提及的问题都遇到了个遍……心灰意冷之时发现,官网的最新package下载好了,反正那么大呢,下载下来还是试试看吧

官网链接传送门来一个

里面的java包,C++包果然还是因为本人比较愚昧一个是一直报错一个是不知道怎么打开……

灵光一闪看到了Python示例,就试试吧,毕竟python是解释性语言,依葫芦画瓢试试看好了,随手敲了一些,上网找了个文件输入输出的例子照着做……然后,居然就成功了……


配置

文件树如下

2015/07/20  23:16    <DIR>          .
2015/07/20  23:16    <DIR>          ..
2015/07/20  19:19    <DIR>          Data
2015/07/20  20:31               511 infile.txt
2015/07/20  20:32    <DIR>          nlpir
2015/07/20  23:22             8,737 nlpir.py
2015/07/20  23:22               649 outfile.txt
2014/01/03  09:42               332 Readme.txt
2015/07/20  20:45    <DIR>          Support
2014/01/02  17:41                 0 __init__.py
               5 个文件         10,229 字节
               5 个目录  2,904,150,016 可用字节


[DIR>DATA]

2015/07/20  20:32    <DIR>          .
2015/07/20  20:32    <DIR>          ..
2014/12/25  14:58                92 20141225.err
2012/05/18  21:36           286,196 BIG2GBK.map
2012/05/18  21:33           468,456 BIG5.pdat
2012/05/18  21:33           158,695 BIG5.wordlist
2009/01/16  13:48         3,520,144 BiWord.big
2012/11/08  20:45            65,540 charset.type
2015/06/03  12:52             3,356 classifier.user
2015/06/03  12:53             3,356 cluster.user
2014/10/31  13:58             1,084 Configure.xml
2009/01/16  13:48         1,696,620 CoreDict.pdat
2009/01/16  13:48         1,786,424 CoreDict.pos
2009/01/16  13:48           478,168 CoreDict.unig
2015/06/03  12:53             3,356 DocExtractor.user
2015/07/20  20:32    <DIR>          English
2014/03/23  20:10           380,016 FieldDict.pdat
2014/03/23  20:10            27,257 FieldDict.pos
2014/03/23  14:55           546,720 FTU8.pdat
2014/03/23  14:55           190,687 FTU8.wordlist
2014/03/23  14:55           286,196 FTU82GBK.map
2012/05/18  21:34           549,204 GBK.pdat
2012/05/18  21:34           166,985 GBK.wordlist
2012/05/18  21:36           286,196 GBK2BIG.map
2014/03/23  14:55           286,196 GBK2FTU8.map
2012/05/18  21:37           286,196 GBK2GBKC.map
2012/05/18  21:37           286,196 GBK2UTF.map
2012/12/22  11:50           550,848 GBKA.pdat
2012/12/22  11:50           166,985 GBKA.wordlist
2012/12/22  11:50           286,196 GBKA2UTF.map
2012/05/18  21:34           550,848 GBKC.pdat
2012/05/18  21:34           166,985 GBKC.wordlist
2012/05/18  21:37           286,196 GBKC2GBK.map
2009/01/16  13:48         1,978,128 GranDict.pdat
2009/01/16  13:48         1,778,776 GranDict.pos
2014/01/03  10:39               422 ICTPOS.map
2015/06/03  12:52             3,356 keyExtract.user
2014/03/18  13:27             3,356 LJHtmlParser.user
2014/03/12  12:47            79,412 location.map
2014/03/12  12:46           416,748 location.pdat
2014/03/12  12:47           106,165 location.wordlist
2014/08/12  10:51             5,100 NewWord.lst
2009/01/16  13:48            37,253 NLPIR.ctx
2015/07/01  14:48             3,356 NLPIR.user
2009/01/16  13:48               288 NLPIR_First.map
2012/11/14  15:57             3,356 NLPIR_trial.user
2009/01/16  13:48             2,213 nr.ctx
2009/01/16  13:48             3,008 nr.fsa
2009/01/16  13:48         1,757,200 nr.role
2014/01/09  15:24               323 PKU.map
2014/01/09  15:24               300 PKU_First.map
2013/09/16  13:32           854,520 sentiment.pdat
2013/09/16  13:33            88,000 sentiment.ung
2015/06/03  12:53             3,356 summary.user
2014/08/12  10:30            33,620 UserDict.pdat
2014/03/23  14:02           286,196 UTF2GBK.map
2012/12/22  11:50           286,196 UTF2GBKA.map
2012/05/18  21:33           557,268 UTF8.pdat
2012/05/18  21:33           190,690 UTF8.wordlist
              56 个文件     22,250,000 字节
               3 个目录  2,904,150,016 可用字节


[DIR>NLPIR]

2015/07/20  20:32    <DIR>          .
2015/07/20  20:32    <DIR>          ..
2013/03/20  09:46         1,027,819 libNLPIR32.so
2013/12/20  13:32         2,014,184 libNLPIR64.so
2013/12/19  21:15            21,533 NLPIR.h
2013/12/19  20:51         1,684,992 NLPIR32.dll
2013/12/19  20:51            11,636 NLPIR32.lib
2014/01/01  21:07         2,301,952 NLPIR64.dll
2014/01/01  21:07            11,678 NLPIR64.lib
2013/11/08  16:48               156 Readme.txt
               8 个文件      7,073,950 字节
               2 个目录  2,904,150,016 可用字节


[DATA>SUPPORT]

2015/07/20  20:45    <DIR>          .
2015/07/20  20:45    <DIR>          ..
2015/07/17  16:11             2,737 Anti-Simply.cpp
2015/07/17  20:50               478 Count.cpp
2015/07/17  23:49               477 FileTest.cpp
2015/07/17  13:51               447 Multifile_Test.cpp
2015/07/20  20:44                87 Readme.md
2015/07/17  16:58             2,848 Simply.cpp
               6 个文件          7,074 字节
               2 个目录  2,904,150,016 可用字节


代码

Python修改后可运行代码如下

# -*- coding: UTF-8 -*-
__author__ = 'Peter_Howe<haobibo@gmail.com>'

'''
Python Warpper for ICTCLAS2014
Loading functions from Dynamic Link Library  directly.
'''
from ctypes import *

#NLPIR2014 Lib File (NLPIR64, NLPIR32, libNLPIR64.so, libNLPIR32.so),
#Change this when you are not using a Win64 environment:
libFile = './nlpir/NLPIR64.dll'

dll =  CDLL(libFile)
def loadFun(exportName, restype, argtypes):
    global dll
    f = getattr(dll,exportName)
    f.restype = restype
    f.argtypes = argtypes
    return f

class ENCODING:
    GBK_CODE        =   0               #默认支持GBK编码
    UTF8_CODE       =   GBK_CODE+1      #UTF8编码
    BIG5_CODE       =   GBK_CODE+2      #BIG5编码
    GBK_FANTI_CODE  =   GBK_CODE+3      #GBK编码,里面包含繁体字

class POSMap:
    ICT_POS_MAP_SECOND  = 0 #计算所二级标注集
    ICT_POS_MAP_FIRST   = 1 #计算所一级标注集
    PKU_POS_MAP_SECOND  = 2 #北大二级标注集
    PKU_POS_MAP_FIRST   = 3	#北大一级标注集

POS = {
	"n": {  #1.	名词  (1个一类,7个二类,5个三类)
		"n":"名词",
		"nr":"人名",
		"nr1":"汉语姓氏",
		"nr2":"汉语名字",
		"nrj":"日语人名",
		"nrf":"音译人名",
		"ns":"地名",
		"nsf":"音译地名",
		"nt":"机构团体名",
		"nz":"其它专名",
		"nl":"名词性惯用语",
		"ng":"名词性语素"
	},
	"t": {  #2.	时间词(1个一类,1个二类)
		"t":"时间词",
		"tg":"时间词性语素"
	},
	"s": {  #3.	处所词(1个一类)
		"s":"处所词"
	},
	"f": {  #4.	方位词(1个一类)
		"f":"方位词"
	},
	"v": {  #5.	动词(1个一类,9个二类)
		"v":"动词",
		"vd":"副动词",
		"vn":"名动词",
		"vshi":"动词“是”",
		"vyou":"动词“有”",
		"vf":"趋向动词",
		"vx":"形式动词",
		"vi":"不及物动词(内动词)",
		"vl":"动词性惯用语",
		"vg":"动词性语素"
	},
	"a": {  #6.	形容词(1个一类,4个二类)
		"a":"形容词",
		"ad":"副形词",
		"an":"名形词",
		"ag":"形容词性语素",
		"al":"形容词性惯用语"
	},
	"b": {  #7.	区别词(1个一类,2个二类)
		"b":"区别词",
		"bl":"区别词性惯用语"
	},
	"z": {  #8.	状态词(1个一类)
		"z":"状态词"
	},
	"r": {  #9.	代词(1个一类,4个二类,6个三类)
		"r":"代词",
		"rr":"人称代词",
		"rz":"指示代词",
		"rzt":"时间指示代词",
		"rzs":"处所指示代词",
		"rzv":"谓词性指示代词",
		"ry":"疑问代词",
		"ryt":"时间疑问代词",
		"rys":"处所疑问代词",
		"ryv":"谓词性疑问代词",
		"rg":"代词性语素"
	},
	"m": {  #10.	数词(1个一类,1个二类)
		"m":"数词",
		"mq":"数量词"
	},
	"q": {  #11.	量词(1个一类,2个二类)
		"q":"量词",
		"qv":"动量词",
		"qt":"时量词"
	},
	"d": {  #12.	副词(1个一类)
		"d":"副词"
	},
	"p": {  #13.	介词(1个一类,2个二类)
		"p":"介词",
		"pba":"介词“把”",
		"pbei":"介词“被”"
	},
	"c": {  #14.	连词(1个一类,1个二类)
		"c":"连词",
		"cc":"并列连词"
	},
	"u": {  #15.	助词(1个一类,15个二类)
		"u":"助词",
		"uzhe":"着",
		"ule":"了 喽",
		"uguo":"过",
		"ude1":"的 底",
		"ude2":"地",
		"ude3":"得",
		"usuo":"所",
		"udeng":"等 等等 云云",
		"uyy":"一样 一般 似的 般",
		"udh":"的话",
		"uls":"来讲 来说 而言 说来",
		"uzhi":"之",
		"ulian":"连 " #(“连小学生都会”)
	},
	"e": {  #16.	叹词(1个一类)
		"e":"叹词"
	},
	"y": {  #17.	语气词(1个一类)
		"y":"语气词(delete yg)"
	},
	"o": {  #18.	拟声词(1个一类)
		"o":"拟声词"
	},
	"h": {  #19.	前缀(1个一类)
		"h":"前缀"
	},
	"k": {  #20.	后缀(1个一类)
		"k":"后缀"
	},
	"x": {  #21.	字符串(1个一类,2个二类)
		"x":"字符串",
		"xx":"非语素字",
		"xu":"网址URL"
	},
	"w":{   #22.	标点符号(1个一类,16个二类)
		"w":"标点符号",
		"wkz":"左括号", 	#( 〔  [  {  《 【  〖 〈   半角:( [ { <
		"wky":"右括号", 	#) 〕  ] } 》  】 〗 〉 半角: ) ] { >
		"wyz":"全角左引号", 	#“ ‘ 『
		"wyy":"全角右引号", 	#” ’ 』
		"wj":"全角句号",	#。
		"ww":"问号",	#全角:? 半角:?
		"wt":"叹号",	#全角:! 半角:!
		"wd":"逗号",	#全角:, 半角:,
		"wf":"分号",	#全角:; 半角: ;
		"wn":"顿号",	#全角:、
		"wm":"冒号",	#全角:: 半角: :
		"ws":"省略号",	#全角:……  …
		"wp":"破折号",	#全角:——   --   ——-   半角:---  ----
		"wb":"百分号千分号",	#全角:% ‰   半角:%
		"wh":"单位符号"	#全角:¥ $ £  °  ℃  半角:$
	}
}

class SegAtom(Structure):
    _fields_ = [("start", c_int32), ("length", c_int32),
        ("sPOS", c_char * 40),      ("iPOS", c_int32),
        ("word_ID", c_int32),       ("word_type", c_int32), ("weight", c_int32)
    ]

def translatePOS(sPOS):
    global POS
    if sPOS=='url': sPOS = 'xu'
    c = sPOS[0]
    return POS[c][sPOS]

Init = loadFun('NLPIR_Init',c_int, [c_char_p, c_int, c_char_p])
Exit = loadFun('NLPIR_Exit',c_bool, None)
ParagraphProcess = loadFun('NLPIR_ParagraphProcess',c_char_p, [c_char_p, c_int])
ParagraphProcessA = loadFun('NLPIR_ParagraphProcessA',POINTER(SegAtom), [c_char_p, c_void_p, c_bool])
#ParagraphProcessAW = loadFun('NLPIR_ParagraphProcessAW',None, [c_int, POINTER(SegAtom)])
FileProcess = loadFun('NLPIR_FileProcess',c_double, [c_char_p, c_char_p, c_int])
ImportUserDict = loadFun('NLPIR_ImportUserDict',c_uint, [c_char_p])
AddUserWord = loadFun('NLPIR_AddUserWord', c_int, [c_char_p])
SaveTheUsrDic = loadFun('NLPIR_SaveTheUsrDic', c_int, None)
DelUsrWord = loadFun('NLPIR_DelUsrWord',c_int, [c_char_p])
GetUniProb = loadFun('NLPIR_GetUniProb', c_double, [c_char_p])
IsWord = loadFun('NLPIR_IsWord',c_bool, [c_char_p])
GetKeyWords = loadFun('NLPIR_GetKeyWords',c_char_p, [c_char_p, c_int, c_bool])
GetFileKeyWords = loadFun('NLPIR_GetNewWords',c_char_p, [c_char_p, c_int, c_bool])
GetNewWords = loadFun('NLPIR_GetNewWords', c_char_p, [c_char_p, c_int, c_bool])
GetFileNewWords = loadFun('NLPIR_GetFileNewWords',c_char_p, [c_char_p, c_int, c_bool])
FingerPrint = loadFun('NLPIR_FingerPrint',c_ulong, [c_char_p])
SetPOSmap = loadFun('NLPIR_SetPOSmap',c_int, [c_int])
#New Word Identification
NWI_Start = loadFun('NLPIR_NWI_Start', c_bool, None)
NWI_AddFile = loadFun('NLPIR_NWI_AddFile',c_bool, [c_char_p])
NWI_AddMem = loadFun('NLPIR_NWI_AddMem',c_bool, [c_char_p])
NWI_Complete = loadFun('NLPIR_NWI_Complete', c_bool, None)
NWI_GetResult = loadFun('NLPIR_NWI_GetResult',c_char_p, [c_int])
NWI_Result2UserDict = loadFun('NLPIR_NWI_Result2UserDict',c_uint, None)

if not Init('',ENCODING.UTF8_CODE,''):
    print("Initialization failed!")
    exit(-111111)

'''
if not SetPOSmap(3): #POSMap.ICT_POS_MAP_SECOND
    print("Setting POS Map failed!")
    exit(-22222)
'''

def seg(paragraph):
    result = ParagraphProcess(paragraph, c_int(1))
    atoms = [i.strip().split('/') for i in result.split(' ') if len(i)>=1 and i[0]!=' ']
    atoms = [(a[0],a[1]) for a in atoms if len(a[0])>0]
    return atoms

def segment(paragraph):
    count = c_int32()
    result = ParagraphProcessA(paragraph, byref(count),c_bool(True))
    count = count.value
    atoms = cast(result, POINTER(SegAtom))
    return [atoms[i] for i in range(0,count)]

def Seg(paragraph):
    atoms = segment(paragraph)
    for a in atoms:
        if len(a.sPOS) < 1: continue
        i = paragraph[a.start: a.start + a.length]#.decode('utf-8')#.encode('ascii')
        yield (i, a.sPOS)

if __name__ == "__main__":
	#p = "Test Article: 中国科学院计算技术研究所在多年研究基础上,耗时一年研制出了基于多层隐码模型的汉语词法分析系统 ICTCLAS(Institute of Computing Technology, Chinese Lexical Analysis System),该系统的功能有:中文分词;词性标注;未登录词识别。分词正确率高达97.58%(最近的973专家组评测结果),基于角色标注的未登录词识别能取得高于90%召回率,其中中国人名的识别召回率接近98%,分词和词性标注处理速度为31.5KB/s。ICTCLAS 和计算所其他14项免费发布的成果被中外媒体广泛地报道,国内很多免费的中文分词模块都或多或少的参考过ICTCLAS的代码。"
	r = open('infile.txt','r')
	f = open('outfile.txt','w')
	for eachline in r:
		p = eachline
		for t in Seg(p):
			#s = '%s\t%s\t%s\n' % (t[0],t[1],translatePOS(t[1]))
			s = '%s\t' % (t[0])
			f.write(s)
		f.write('\n')
	f.close()


使用说明

需要改动的应该只有main函数了,被注释的部分中,t[0]是分词结果,t[1]是这个被分出来的词的词性,translatePOS(t[1])则是将其分离出来所用到的规则(理论依据)

示例:

infile.txt

中国科学院计算技术研究所在多年研究基础上
耗时一年研制出了基于多层隐码模型的汉语词法分析系统
ICTCLAS(Institute of Computing Technology, Chinese Lexical Analysis System)
该系统的功能有:中文分词;词性标注;未登录词识别。
分词正确率高达97.58%(最近的973专家组评测结果),
基于角色标注的未登录词识别能取得高于90%召回率,
其中中国人名的识别召回率接近98%,
分词和词性标注处理速度为31.5KB/s。
ICTCLAS 和计算所其他14项免费发布的成果被中外媒体广泛地报道

outfile.txt

中	国	科学院	计算	技术	研	究	所在	多	年	研	究	基础	上	
耗时	一	年	研制	出	了	基于	多	层	隐	码	模型	的	汉语	词法	分析	系统	
ICTCLAS	(	Institute	of	Computing	Technology	,	Chinese	Lexical	Analysis	System	)	
该	系统	的	功能	有	:	中文	分词	;	词性	标注	;	未	登录	词	识别	。	
分词	正确	率	高	达	97.58%	(	最近	的	973	专家组	评测	结果	)	,	
基于	角色	标注	的	未	登录	词	识别	能	取得	高于	90%	召回	率	,	
其中	中	国	人名	的	识别	召回	率	接近	98%	,	
分词	和	词性	标注	处理	速度	为	31.5KB/s	。	
ICTCLAS	和	计算	所	其他	14	项	免费	发布	的	成果	被	中外	媒体	广泛	地	报道	

After TranslatePOS(t[1])

中国科学院	nt	机构团体名
计算	v	动词
技术	n	名词
研究	vn	名动词
所	usuo	所
在	v	动词
多年	mq	数量词
研究	vn	名动词
基础	n	名词
上	f	方位词

耗时	vi	不及物动词(内动词)
一	m	数词
年	qt	时量词
研制	v	动词
出	vf	趋向动词
了	ule	了 喽
基于	p	介词
多	m	数词
层	qv	动量词
隐	v	动词
码	q	量词
模型	n	名词
的	ude1	的 底
汉语	nz	其它专名
词法	n	名词
分析	vn	名动词
系统	n	名词

ICTCLAS	x	字符串
(	wkz	左括号
Institute	x	字符串
of	x	字符串
Computing	x	字符串
Technology	x	字符串
,	wd	逗号
Chinese	x	字符串
Lexical	x	字符串
Analysis	x	字符串
System	x	字符串
)	wky	右括号

该	rz	指示代词
系统	n	名词
的	ude1	的 底
功能	n	名词
有	vyou	动词“有”
:	wp	破折号
中文	nz	其它专名
分词	v	动词
;	wf	分号
词性	n	名词
标注	v	动词
;	wf	分号
未	d	副词
登录	v	动词
词	n	名词
识别	vn	名动词
。	wj	全角句号

分词	v	动词
正确	ad	副形词
率	v	动词
高	ad	副形词
达	v	动词
97.58%	m	数词
(	wkz	左括号
最近	t	时间词
的	ude1	的 底
973	m	数词
专家组	n	名词
评测	vn	名动词
结果	n	名词
)	wky	右括号
,	wd	逗号

基于	p	介词
角色	n	名词
标注	v	动词
的	ude1	的 底
未	d	副词
登录	v	动词
词	n	名词
识别	v	动词
能	v	动词
取得	v	动词
高于	v	动词
90%	m	数词
召回	v	动词
率	v	动词
,	wd	逗号

其中	rz	指示代词
中国	ns	地名
人	n	名词
名	q	量词
的	ude1	的 底
识别	vn	名动词
召回	v	动词
率	k	后缀
接近	v	动词
98%	m	数词
,	wd	逗号

分词	v	动词
和	cc	并列连词
词性	n	名词
标注	v	动词
处理	v	动词
速度	n	名词
为	v	动词
31.5KB/s	url	网址URL
。	wj	全角句号

ICTCLAS	x	字符串
和	cc	并列连词
计算	vn	名动词
所	n	名词
其他	rzv	谓词性指示代词
14	m	数词
项	q	量词
免费	vd	副动词
发布	v	动词
的	ude1	的 底
成果	n	名词
被	pbei	介词“被”
中外	b	区别词
媒体	n	名词
广泛	a	形容词
地	ude2	地
报道	v	动词


Source_Code

Python.Ver Demo

Github, 向张华平博士致敬

Python.Ver Ofiicial Demo

Github. Tsroten/pynlpir

Github. Haobio


评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

糖果天王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值