最近在查找关于中文分词解析方面的开源工具,最开始找到了腾讯的文智与百度的自然语言,这两个平台都是对外提供HTTP接口调用需要把数据传输过去返回解析结果。
使用这种方式会有两种隐患:1.要确定网络情况;2.数据保密性;
在此基础上找到了NLPIR分词系统,下面来介绍一下使用方式,这里使用NLPIR的基础上完成二次开发。
jdk1.7-64/win7-64/myeclipse8.5
NLPIR官方网址:http://ictclas.nlpir.org/ 提供有在线演示效果,并且官网有下载地址,NLPIR下载地址托管在github平台 https://github.com/NLPIR-team/NLPIR
下载一个NLPIR-master.zip的压缩包,这个下面有几个文件夹分别存放着各种功能
主要文件介绍:
License:存放需要调动每个功能的用户信息
NLPIR SDK:基于二次开发插件
NLPIR-Parser:NLPIR客户端使用
LicenseClient:用户注册信息
打开上面所叙述的NLPIR SDK文件夹
NLPIR-master\NLPIR SDK\NLPIR-ICTCLAS
projects:下各种语言基于二次开发的插件与资料,直接下载里面提供的官方示例,只需修改个人NLPIR.user文件 直接使用
官方示例:https://github.com/NLPIR-team/NLPIR-ICTCLAS
注意:添加jre后直接Main方法运行NLPIRTest.java,但是会报错
lib\Data\NLPIR.user Not valid license or your license expired! Please feel free to contact pipy_zhang@msn.com!
data_train\4-1_01
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokePointer(Native Method)
at com.sun.jna.Function.invokePointer(Function.java:470)
at com.sun.jna.Function.invokeString(Function.java:651)
at com.sun.jna.Function.invoke(Function.java:395)
at com.sun.jna.Function.invoke(Function.java:315)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy0.NLPIR_ParagraphProcess(Unknown Source)
at com.lingjoin.nlpir.NLPIR.paragraphProcess(NLPIR.java:45)
at com.lingjoin.nlpir.test.NLPIRTest.main(NLPIRTest.java:42)
异常是由于官方工程示例中的lib\Data\NLPIR.user 无法使用,需要使用自己本地中的NLPIR.user文件,
NLPIR.user地址:
1.NLPIR-master\License\license for a month\NLPIR-ICTCLAS分词系统授权\NLPIR.user
2.NLPIR-master\NLPIR SDK\NLPIR-ICTCLAS\Data\NLPIR.user
这两个文件均可
再次运行即可NLPIRTest.java正常使用
调取接口方法说明
package com.lingjoin.nlpir;
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface CNLPIRLibrary extends Library {
//根据当前计算机环境决定使用resources下的NLPIR.dll插件,我这里是win7-64
CNLPIRLibrary Instance = (CNLPIRLibrary) Native.loadLibrary("NLPIR", CNLPIRLibrary.class);
/**
* 初始化
* @param sDataPath Data目录所在路径
* @param encoding 编码,0是GBK,1是UTF8
* @param sLicenceCode 为空即可
* @return
*/
public boolean NLPIR_Init(String sDataPath, int encoding, String sLicenceCode);
/**
* 分词接口,主要调用此接口解析字符串完成分词
* @param sParagraph 待分词串
* @param bPOSTagged 是否带词性
* @return
*/
public String NLPIR_ParagraphProcess(String sParagraph, int bPOSTagged);
public int NLPIR_GetParagraphProcessAWordCount(String para);
public String NLPIR_FinerSegment(String lenWords);
public int NLPIR_ImportUserDict(String dictFileName, boolean bOverwrite);
public int NLPIR_ImportKeyBlackList(String sFilename);
public String NLPIR_GetWordPOS(String sWords);
public boolean NLPIR_IsWord(String word);
public String NLPIR_WordFreqStat(String sText);
public String NLPIR_FileWordFreqStat(String sFilename);
public String NLPIR_GetEngWordOrign(String sWord);
public double NLPIR_GetUniProb(String word);
//对TXT文件内容进行分词
public double NLPIR_FileProcess(String sSourceFilename,String sResultFilename, int bPOStagged);
//从字符串中提取关键词
public String NLPIR_GetKeyWords(String sLine, int nMaxKeyLimit,boolean bWeightOut);
//从TXT文件中提取关键词
public String NLPIR_GetFileKeyWords(String sLine, int nMaxKeyLimit,boolean bWeightOut);
//添加单条用户词典
public int NLPIR_AddUserWord(String sWord);
//删除单条用户词典
public int NLPIR_DelUsrWord(String sWord);
//从TXT文件中导入用户词典
public int NLPIR_ImportUserDict(String sFilename);
//将用户词典保存至硬盘
public boolean NLPIR_SaveTheUsrDic();
//从字符串中获取新词
public String NLPIR_GetNewWords(String sLine, int nMaxKeyLimit, boolean bWeightOut);
//从TXT文件中获取新词
public String NLPIR_GetFileNewWords(String sTextFile,int nMaxKeyLimit, boolean bWeightOut);
//获取一个字符串的指纹值
public long NLPIR_FingerPrint(String sLine);
//设置要使用的POS map
public int NLPIR_SetPOSmap(int nPOSmap);
//获取报错日志
public String NLPIR_GetLastErrorMsg();
//退出
public void NLPIR_Exit();
}
NLPIR方法二次封装
package com.lingjoin.nlpir;
/**
* NLPIR方法二次封装
* @author Pan
*/
public class NLPIR {
//初始化状态
public static boolean InitState=false;
//初始化方法
public static boolean init(String argu){
int charsetType=1;
InitState=CNLPIRLibrary.Instance .NLPIR_Init(argu,charsetType,"0");
if(InitState){
return InitState;
}else{
System.out.println(CNLPIRLibrary.Instance.NLPIR_GetLastErrorMsg());
return false;
}
}
public static boolean Init(){
int charsetType=1;
String argu="";
InitState=CNLPIRLibrary.Instance .NLPIR_Init(argu,charsetType,"0");
if(InitState){
return InitState;
}else{
System.out.println(CNLPIRLibrary.Instance.NLPIR_GetLastErrorMsg());
return false;
}
}
/**
* NLPIR分词方法
* @param sSrc 待分词字符串
* @param bPOSTagged 分词标注集序号
* 0----为无标注分词结果集,
* 1---- ICT_POS_MAP_FIRST 计算所一级标注集
* 2-----ICT_POS_MAP_SECOND 计算所二级标注集
* 3-----PKU_POS_MAP_SECOND 北大二级标注集
* 4-----PKU_POS_MAP_FIRST 北大一级标注集
* @return
*/
public static String paragraphProcess(String sSrc, int bPOSTagged){
String result=null;
try{
result=CNLPIRLibrary.Instance.NLPIR_ParagraphProcess(sSrc, bPOSTagged);
}catch(Exception e){
System.out.println(CNLPIRLibrary.Instance.NLPIR_GetLastErrorMsg());
}
return result;
}
public static int getParagraphProcessAWordCount(String para){
if(!InitState){
return 0;
}else
return CNLPIRLibrary.Instance.NLPIR_GetParagraphProcessAWordCount(para);
}
public static String finerSegment(String lenWords){
if(!InitState){
return null;
}else
return CNLPIRLibrary.Instance.NLPIR_FinerSegment(lenWords);
}
public static long fingerPrint(String sLine){
if(!InitState){
return 0;
}else
return CNLPIRLibrary.Instance.NLPIR_FingerPrint(sLine);
}
public static boolean isWord(String word){
if(!InitState){
return false;
}else
return CNLPIRLibrary.Instance.NLPIR_IsWord(word);
}
public static String wordFreqStat(String sText){
if(!InitState){
return null;
}else
return CNLPIRLibrary.Instance.NLPIR_WordFreqStat(sText);
}
public static String getEngWordOrign(String sWord){
if(!InitState){
return null;
}else
return CNLPIRLibrary.Instance.NLPIR_GetEngWordOrign(sWord);
}
public static double getUniProb(String word){
if(!InitState){
return 0.0;
}else
return CNLPIRLibrary.Instance.NLPIR_GetUniProb(word);
}
public static String getWordPos(String str){
String result="";
String pos="";
if(!InitState){
System.out.println("请先初始化分词!");
return null;
}
try{
pos=CNLPIRLibrary.Instance.NLPIR_GetWordPOS(str);
//System.out.println(pos);
if(!pos.contains("#")) return "un";
String[] p=pos.split("#");
if(p.length>1){
for(int i=0;i<p.length;i++){
if(i==0) result+=p[i].split("/")[1]+"#";
else if(i==p.length-1) result+=p[i].split("/")[1];
else result+=p[i].split("/")[1]+"#";
}
return result;
}else{
result=pos.split("/")[1];
}
}catch(Exception e){
System.out.println("参数解析失败!");
}
return result;
}
/**
* 添加用户词典
* @param fileDict
*/
public static int importUserDict(String fileDict){
if(!InitState){
return 0;
}
return CNLPIRLibrary.Instance.NLPIR_ImportUserDict(fileDict,true);
}
public static int NLPIR_ImportKeyBlackList(String sFilename){
if(!InitState){
return 0;
}else
return CNLPIRLibrary.Instance.NLPIR_ImportKeyBlackList(sFilename);
}
/**
* 添加用户词
* @param word
* @return
*/
public static boolean addUserWord(String word){
if(!InitState){
System.out.println("请先初始化分词!");
return false ;
}
int addState= CNLPIRLibrary.Instance.NLPIR_AddUserWord(word);
if(addState==0)
return false;
else
return true;
}
/**
* 保存用户词典
*/
public static boolean saveUserWord(){
return CNLPIRLibrary.Instance.NLPIR_SaveTheUsrDic();
}
public static boolean deleteUserWord(String word){
if(!InitState){
System.out.println("请先初始化分词!");
return false ;
}
int delState=CNLPIRLibrary.Instance.NLPIR_DelUsrWord(word);
if(delState==-1){
System.out.print("The word :"+word+"not exsit!");
return false;
}else
return true;
}
public static String getLastErrorMsg(){
return CNLPIRLibrary.Instance.NLPIR_GetLastErrorMsg();
}
/**
* 退出
*/
public static void Exit(){
if(!InitState){
System.out.println("未初始化分词!无需执行退出操作!");
}
CNLPIRLibrary.Instance.NLPIR_Exit();
}
public static void main(String[] args) throws Exception {
NLPIR.init("lib");
System.out.println(NLPIR.isWord("中国"));
}
}
NLPIRTest测试
package com.lingjoin.nlpir.test;
import java.io.File;
import java.io.FileWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import com.lingjoin.nlpir.NLPIR;
public class NLPIRTest {
/**
* 存放某个路径下的所有文件地址
*/
List<String> files=new ArrayList<String>();
/**
* 当前文件夹下的所有文件路径获取
* @param filePath 文件夹地址
*/
public void getAllfiles(File filePath){
File[] fsFiles=filePath.listFiles();
for(File f:fsFiles){
if(f.isFile()&&!f.getName().equals(".DS_Store")) files.add(f.getPath());
if(f.isDirectory()) this.getAllfiles(f);
}
}
/**
* 加载本地文件中的字符串至内存中
* @param file 文件地址
* @return 文件中字符串
* @throws Exception
*/
public String getContent(File file)throws Exception{
RandomAccessFile f=new RandomAccessFile(file, "r");
byte[] b=new byte[(int) file.length()];
f.read(b);
f.close();
String c=new String(b,"GBK").replaceAll("\\s", "");
return c;
}
public static void main(String[] args)throws Exception{
//1.初始化
NLPIR.init("lib");
//NLPIR.importUserDict("");
//2.字符串分词后存放地址
FileWriter fw=new FileWriter(new File("seg.txt"));
//3.待分词文件地址
String fPath="data_train";
NLPIRTest test=new NLPIRTest();
//4.加载待分词文件地址
test.getAllfiles(new File(fPath));
//5.遍历解析待分析文件
for(String f:test.files){
System.out.println(f);
//6.加载文件内容至内存中
String con=test.getContent(new File(f));
//7.分词处理,存放结果
fw.write(new File(f).getName()+"\t"+NLPIR.paragraphProcess(con, 1).replaceAll(" ", "\t")+"\n");
}
fw.flush();
fw.close();
}
}
加载当前工程data_train文件夹下的文件字符内容至内存中调用分词接口将解析后的结果存入seg.txt文件
NLPIR-ICTCLAS-master\data_train\4-1_01 文件
新华社照片,枣庄(山东),2016年8月30日
山东枣庄出现“鱼鳞云”
这是8月30日在山东省枣庄市山亭区翼云湖畔拍摄的“鱼鳞云”。
当日清晨,山东省枣庄市山亭区上空出现大面积“鱼鳞云”,在初秋蓝天的映衬下,美不胜收。
新华社发(李宗宪 摄)
解析后的内容
新华社/nt 照片/n ,/wd 枣庄/ns (/wkz 山东/ns )/wky ,/wd 2016年/t 8月/t 30日/t 山东/ns 枣庄/ns 出现/v “/wyz 鱼鳞/n 云/vg ”/wyy 这/rzv 是/vshi 8月/t 30日/t 在/p 山东省/ns 枣庄市/ns 山亭区/ns 翼/ng 云/vg 湖畔/n 拍摄/v 的/ude1 “/wyz 鱼鳞/n 云/vg ”/wyy 。/wj 当日/t 清晨/t ,/wd 山东省/ns 枣庄市/ns 山亭区/ns 上空/s 出现/v 大/a 面积/n “/wyz 鱼鳞/n 云/vg ”/wyy ,/wd 在/p 初秋/t 蓝天/n 的/ude1 映衬/vn 下/f ,/wd 美不胜收/vl 。/wj 新华社/nt 发/v (/wkz 李宗宪/nr 摄/vg )/wky
自定义字符串测试结果
@Test
public void test(){
NLPIR.init("lib");
String con = "当日清晨,山东省枣庄市山亭区上空出现大面积“鱼鳞云”,在初秋蓝天的映衬下,美不胜收。 ";
String paragraphProcess = NLPIR.paragraphProcess(con, 1);
System.out.println("解析后的内容:"+paragraphProcess);
/**
* 解析后的内容:当日/t 清晨/t ,/wd 山东省/ns 枣庄市/ns 山亭区/ns 上空/s 出现/v 大/a 面积/n “/wyz 鱼鳞/n 云/vg ”/wyy ,/wd 在/p 初秋/t 蓝天/n 的/ude1 映衬/vn 下/f ,/wd 美不胜收/vl 。/wj
*/
}
参考博客:
接口调用:https://blog.csdn.net/SUN_song520/article/details/51996844
错误解决:https://blog.csdn.net/wangjinyang_123/article/details/50417557
我所有的资料都是在官网下载的,这里就不上传工程了。