本文只适用于 python-nlpir V1.0 版本,有关 V2.0
版本详情参照项目源代码。
python-nlpir 是 NLPIR 中文分词工具的 Python 封装,利用 SWIG 完成
C++到 python 的接口转换。
项目地址: https://github.com/zhenlohuang/python-nlpir
NLPIR 汉语分词系统(又名
ICTCLAS2013),主要功能包括中文分词;词性标注;命名实体识别;用户词典功能;支持
GBK 编码、UTF8 编码、BIG5
编码。新增微博分词、新词发现与关键词提取;是当前最好的中文分词工具之一。
1、使用 SWIG 进行接口转换
SWIG 是个帮助使用 C 或者
C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。SWIG
能应用于各种不同类型的语言包括常用脚本编译语言例如 Perl, PHP, Python,
Tcl, Ruby and PHP。支持语言列表中也包括非脚本编译语言,例如 C#, Common
Lisp (CLISP, Allegro CL, CFFI, UFFI), Java, Modula-3, OCAML 以及
R,甚至是编译器或者汇编的计划应用(Guile, MzScheme, Chicken)。SWIG
普遍应用于创建高级语言解析或汇编程序环境,用户接口,作为一种用来测试
C/C++或进行原型设计的工具。SWIG 还能够导出 XML 或 Lisp s-expressions
格式的解析树。SWIG 可以被自由使用,发布,修改用于商业或非商业中。
1)编写 interface 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 %module NLPIR %{ #define SWIG_FILE_WITH_INIT #include "NLPIR.h" %} #define POS_MAP_NUMBER 4 #define ICT_POS_MAP_FIRST 1 #define ICT_POS_MAP_SECOND 0 #define PKU_POS_MAP_SECOND 2 #define PKU_POS_MAP_FIRST 3 #define POS_SIZE 40 #define GBK_CODE 0 #define UTF8_CODE GBK_CODE+1 #define BIG5_CODE GBK_CODE+2 #define GBK_FANTI_CODE GBK_CODE+3 bool NLPIR_Init (const char * sDataPath=0 ,int encode=GBK_CODE,const char *sLicenceCode=0 ) ;bool NLPIR_Exit () ;const char * NLPIR_ParagraphProcess (const char *sParagraph,int bPOStagged=1 ) ;const result_t * NLPIR_ParagraphProcessA (const char *sParagraph,int *pResultCount,bool bUserDict=true ) ;int NLPIR_GetParagraphProcessAWordCount (const char *sParagraph) ;void NLPIR_ParagraphProcessAW (int nCount,result_t * result) ;double NLPIR_FileProcess (const char *sSourceFilename,const char *sResultFilename,int bPOStagged=1 ) ;unsigned int NLPIR_ImportUserDict (const char *sFilename) ;int NLPIR_AddUserWord (const char *sWord) ;int NLPIR_SaveTheUsrDic () ;int NLPIR_DelUsrWord (const char *sWord) ;double NLPIR_GetUniProb (const char *sWord) ;bool NLPIR_IsWord (const char *sWord) ;const char * NLPIR_GetKeyWords (const char *sLine,int nMaxKeyLimit=50 ,bool bWeightOut=false ) ;const char * NLPIR_GetFileKeyWords (const char *sFilename,int nMaxKeyLimit=50 ,bool bWeightOut=false ) ;const char * NLPIR_GetNewWords (const char *sLine,int nMaxKeyLimit=50 ,bool bWeightOut=false ) ;const char * NLPIR_GetFileNewWords (const char *sFilename,int nMaxKeyLimit=50 ,bool bWeightOut=false ) ;unsigned long NLPIR_FingerPrint (const char *sLine) ;int NLPIR_SetPOSmap (int nPOSmap) ;bool NLPIR_NWI_Start () ;int NLPIR_NWI_AddFile (const char *sFilename) ;bool NLPIR_NWI_AddMem (const char *sText) ;bool NLPIR_NWI_Complete () ;const char * NLPIR_NWI_GetResult (bool bWeightOut=false ) ;unsigned int NLPIR_NWI_Result2UserDict () ;
2)接口转换
1 swig -c++ -python NLPIR.interface
执行完成接口转换后,将生成 NLPIR_wrap.cxx、NLPIR.py
两个文件,到目前为止已经完成了接口的转换,不过现在接口还不能使用,因为还没有编译好相应的库。
2、编写 setup.py 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ''' setup.py file for NLPIR ''' from distutils.core import setup, ExtensionNLPIR_module = Extension('_NLPIR' ,sources=['NLPIR_wrap.cxx' ], libraries = ['NLPIR' ]) setup(name = 'NLPIR' , version = '1.1' , author = 'Killua' , description = 'Python for NLPIR' , ext_modules = [NLPIR_module], py_modules = ['NLPIR' ], )
3、编译代码
1)复制 libNLPIR.so 到/usr/lib
目录下
1 sudo cp libNLPIR.so /usr/lib
2)修改 NLPIR.h 文件
由于原来的 NLPIR.h 在 gcc
编译器中的兼容性并不好,所以需要对原来的头文件进行简单的修改。
将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #ifdef OS_LINUX #define NLPIR_API #else #ifdef NLPIR_EXPORTS #ifdef CSHARP_API #define NLPIR_API extern "C" __declspec(dllexport) #else #define NLPIR_API __declspec(dllexport) #endif #else #ifdef CSHARP_API #define NLPIR_API extern "C" __declspec(dllimport) #else #define NLPIR_API __declspec(dllimport) #endif #endif #endif #if defined(NLPIR_JNI_EXPORTS)||defined(KEYEXTRACT_EXPORTS) #define NLPIR_API #endif
改为
1 2 3 4 5 6 7 8 9 #ifdef linux #define NLPIR_API #elif _WIN32 || _WIN64 #ifdef NLPIR_EXPORTS #define NLPIR_API __declspec(dllexport) #else #define NLPIR_API __declspec(dllimport) #endif #endif
将
1 2 3 4 5 #ifdef OS_LINUX class CNLPIR {#else class __declspec (dllexport) CNLPIR {#endif
改为
1 2 3 4 5 #ifdef linux class CNLPIR {#else class __declspec (dllexport) CNLPIR {#endif
3)编译代码
1 python setup.py build_ext --inplace
4、编写 PyNLPIR.py
为了方便使用对生成的 NLPIR.py 进行重封装。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 ''' Created on Fri 19, 2013 @author: killua @e-mail: [email protected] @Decription: Python for NLPIR ''' import NLPIRimport osdef nlpir_init (init_dir = '.' , code_type = 'GBK' ): ''' Init the analyzer and prepare necessary data for NLPIR according the configure file. ''' if code_type == 'GBK' : is_succeed = NLPIR.NLPIR_Init(init_dir, NLPIR.GBK_CODE) elif code_type == 'UTF-8' or code_type == 'UTF8' : is_succeed = NLPIR.NLPIR_Init(init_dir, NLPIR.UTF8_CODE) elif code_type == 'BIG5' : is_succeed = NLPIR.NLPIR_Init(init_dir, NLPIR.BIG5_CODE) elif code_type == 'GBK_FANTI' : is_succeed = NLPIR.NLPIR_Init(init_dir, NLPIR.GBK_FANTI_CODE) if is_succeed: print 'NLPIR Successful.' else : print 'NLPIR Failed.' def nlpir_exit (): ''' Exit the program and free all resources and destroy all working buffer used in NLPIR. ''' return NLPIR.NLPIR_Exit() def nlpir_import_user_dict (user_dict ): ''' Import user-defined dictionary from a text file. ''' return NLPIR.NLPIR_ImportUserDict(user_dict) def nlpir_paragraph_process (text, is_pos_tagged = False ): ''' Process a paragraph ''' return NLPIR.NLPIR_ParagraphProcess(text, is_pos_tagged) def nlpir_file_process (source_file, target_file, is_pos_tagged = False ): ''' Process a text file ''' return NLPIR.NLPIR_FileProcess(source_file, target_file, is_pos_tagged) def nlpir_add_user_word (word ): ''' Add a word to the user dictionary. ''' return NLPIR.NLPIR_AddUserWord(word) def nlpir_save_user_dict (): ''' Save the user dictionary to disk. ''' return NLPIR.NLPIR_SaveTheUsrDic() def nlpir_delete_user_word (word ): ''' Delete a word from the user dictionary. ''' return NLPIR.NLPIR_DelUsrWord(word)
测试
编写 demo.py
1 2 3 4 5 6 7 8 9 10 11 12 from PyNLPIR import *if __name__ == '__main__' : nlpir_init('.' , 'UTF-8' ) print nlpir_paragraph_process(r'@ICTCLAS张华平博士 应各位ICTCLAS用户的要求,张华平博士提前发布ICTCLAS2013 版本,为了与以前工作进行大的区隔,并推广NLPIR自然语言处理与信息检索共享平台,从本版本开始,系统名称调整为NLPIR汉语分词系统。' ) print print nlpir_paragraph_process(r'“屌丝”这个嘲讽意味的代词迅速爆红,迎合了大众的心理和趣味。因为你会发现从表面符合屌丝定义的人,到和屌丝属性八竿子打不着的人,都在争相认领这一名号。当人人都在忙着确认自己的屌丝身份,并乐此不疲时,屌丝一词一定与时代的什么特征实现了合拍。“屌丝”不是阿Q,他们公然比惨并乐在其中有评论认为,“屌丝”是新时代的阿Q,两者并不完全相同。首先,阿Q是文学巨匠鲁迅一己之力创造的,而“屌丝”则是网络群体狂欢的结果,它是真正由网民集体创作的形象;另外,阿Q最重要的特征是“精神胜利法”,梦想的是“银盔银甲”,意淫的是“我手持钢鞭将你打”。' , True ) nlpir_exit()
运行结果
常见问题
“Unable to find vcvarsall.bat”解决办法
参见:http://www.yidooo.net/archives/unable-to-find-vcvarsall-bat-solution.html
提示找不到_NLPIR 模块提示找不到_NLPIR 模块的文件
Windows:将 NLPIR.dll copy 到 System32 下
Linux:将 libNLPIR.so copy 到/usr/lib 或者/usr/lib64 下
请参考:http://ictclas.nlpir.org/newsDetail?DocId=386
Change Log
Date: 2013-11-15
添加对 Window 64bit 和 Linux 64bit 的支持。
对项目文件结构进行调整,将 library 文件进行分离。
将 NLPIR 升级到最新版本。
感谢
Version 1.1: 感谢zzdwcm ,所提供有关 Linux 64bit
的补丁。
参考资料
http://ictclas.nlpir.org/
http://www.nilday.com/nlpirictclas2013-python%E7%89%88/
https://github.com/ch0psticks/nlpir-python-win32