如何使用中科院分词系统(java版)

做数据挖掘,分词是很重要、很基础的一个环节。单独实现一个分词系统并不是一件简单的事情,特别是对于中文而言。好在中科院已经有一套开源的分词系统NLPIR,我们可以直接拿来使用,很方便。下面我就记录一下基于java怎么使用这套系统。

首先看一下关于分词系统的简介

NLPIR汉语分词系统(又名ICTCLAS2013),主要功能包括中文分词;词性标注;命名实体识别;用户词典功能;支持GBK编码、UTF8编码、BIG5编码。新增微博分词、新词发现与关键词提取;张华平博士先后倾力打造十余年,内核升级10次。

我们首先到官网的下载页面:http://ictclas.nlpir.org/downloads

下载第一个“NLPIR/ICTCLAS2015分词系统下载包”即可,如下图

中科院分词系统

下载之后,解压缩。

进入子目录下的sample文件夹,你会看到有各种示例,我们要用的是java的示例,即“JnaTest_NLPIR”,如下图:

分词系统java示例

打开eclipse,import这个工程,过程就不再赘述了。

import之后,这时候你去跑,是会报错的。

java报错

其实,我们需要改几个地方。

1.回到刚才解压的下载包,进入目录下的lib文件夹,选择你机器对应的版本,比如我是win32的,我就复制win32这个文件夹,粘贴到eclipse工程和src同级目录下,此时工作目录应是如图所示:

添加win32文件夹

2.修改第一行的代码,将NLPIR文件的路径更改为现在的路径,如下:

// 定义并初始化接口的静态变量
CLibrary Instance = (CLibrary) Native.loadLibrary(
       "./win32/NLPIR", CLibrary.class);

3.回到解压的文件夹目录下,复制“data”文件夹到eclipse的工程里,最终工程目录结构如下:

最终目录结构

4.更改主函数的第一行代码里面的路径,默认是这样:

String argu = "D:\\NLPIR";

更改为:

String argu = "./";

即工作路径。

最终代码如下:

package code;

import java.io.UnsupportedEncodingException;

import utils.SystemParas;

import com.sun.jna.Library;
import com.sun.jna.Native;

public class NlpirTest {

	// 定义接口CLibrary,继承自com.sun.jna.Library
	public interface CLibrary extends Library {
		// 定义并初始化接口的静态变量
		CLibrary Instance = (CLibrary) Native.loadLibrary(
				"./win32/NLPIR", CLibrary.class);

		public int NLPIR_Init(String sDataPath, int encoding,
				String sLicenceCode);

		public String NLPIR_ParagraphProcess(String sSrc, int bPOSTagged);

		public String NLPIR_GetKeyWords(String sLine, int nMaxKeyLimit,
				boolean bWeightOut);
		public String NLPIR_GetFileKeyWords(String sLine, int nMaxKeyLimit,
				boolean bWeightOut);
		public int NLPIR_AddUserWord(String sWord);//add by qp 2008.11.10
		public int NLPIR_DelUsrWord(String sWord);//add by qp 2008.11.10
		public String NLPIR_GetLastErrorMsg();
		public void NLPIR_Exit();
	}

	public static String transString(String aidString, String ori_encoding,
			String new_encoding) {
		try {
			return new String(aidString.getBytes(ori_encoding), new_encoding);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) throws Exception {
		String argu = "./";
		// String system_charset = "GBK";//GBK----0
		String system_charset = "UTF-8";
		int charset_type = 1;

		int init_flag = CLibrary.Instance.NLPIR_Init(argu, charset_type, "0");
		String nativeBytes = null;

		if (0 == init_flag) {
			nativeBytes = CLibrary.Instance.NLPIR_GetLastErrorMsg();
			System.err.println("初始化失败!fail reason is "+nativeBytes);
			return;
		}

		String sInput = "据悉,质检总局已将最新有关情况再次通报美方,要求美方加强对输华玉米的产地来源、运输及仓储等环节的管控措施,有效避免输华玉米被未经我国农业部安全评估并批准的转基因品系污染。";

		//String nativeBytes = null;
		try {
			nativeBytes = CLibrary.Instance.NLPIR_ParagraphProcess(sInput, 1);

			System.out.println("分词结果为: " + nativeBytes);

			CLibrary.Instance.NLPIR_AddUserWord("要求美方加强对输 n");
			CLibrary.Instance.NLPIR_AddUserWord("华玉米的产地来源 n");
			nativeBytes = CLibrary.Instance.NLPIR_ParagraphProcess(sInput, 1);
			System.out.println("增加用户词典后分词结果为: " + nativeBytes);

			CLibrary.Instance.NLPIR_DelUsrWord("要求美方加强对输");
			nativeBytes = CLibrary.Instance.NLPIR_ParagraphProcess(sInput, 1);
			System.out.println("删除用户词典后分词结果为: " + nativeBytes);

			int nCountKey = 0;
			String nativeByte = CLibrary.Instance.NLPIR_GetKeyWords(sInput, 10,false);

			System.out.print("关键词提取结果是:" + nativeByte);

			nativeByte = CLibrary.Instance.NLPIR_GetFileKeyWords("D:\\NLPIR\\feedback\\huawei\\5341\\5341\\产经广场\\2012\\5\\16766.txt", 10,false);

			System.out.print("关键词提取结果是:" + nativeByte);

			CLibrary.Instance.NLPIR_Exit();

		} catch (Exception ex) {
			// TODO Auto-generated catch block
			ex.printStackTrace();
		}

	}
}

运行结果如下(截图不完全,请以你的eclipse的输出为准):

中科院分词系统运行结果

 

至此,一个例子就跑起来了。我稍微解释一下。

1.关于结果

分词的结果,是每个词语后面再跟一个斜杠,斜杠后面是词性,关于词性,可以参看刚才下载解压的文件目录下的“doc”文件夹里的文档。这里不做解释了。

当然,你也可以选择不要显示词性,只需将

CLibrary.Instance.NLPIR_ParagraphProcess(sInput, 1);

中第二个参数改为0即可。

2.关于方法的调用

这套分词系统里面有丰富的功能,这个可以参看“doc”文件夹里面的文档,那里均有说明,由于使用了JNA,我们可以很方便的使用相关的c++方法。

要使用这些功能,我们需要在代码的接口中声明这些方法,如:

public interface CLibrary extends Library {
		// 定义并初始化接口的静态变量
		CLibrary Instance = (CLibrary) Native.loadLibrary(
				"./win32/NLPIR", CLibrary.class);

		public int NLPIR_Init(String sDataPath, int encoding,
				String sLicenceCode);

		public String NLPIR_ParagraphProcess(String sSrc, int bPOSTagged);

		public String NLPIR_GetKeyWords(String sLine, int nMaxKeyLimit,
				boolean bWeightOut);
		public String NLPIR_GetFileKeyWords(String sLine, int nMaxKeyLimit,
				boolean bWeightOut);
		public int NLPIR_AddUserWord(String sWord);//add by qp 2008.11.10
		public int NLPIR_DelUsrWord(String sWord);//add by qp 2008.11.10
		public String NLPIR_GetLastErrorMsg();
		public void NLPIR_Exit();
	}

声明之后,就可以在主函数里面调用了。具体的调用细节、参数设定等,还是那句话,看文档!

就先写到这里,再次感慨中科院的分词系统的厉害!