在之前的文章中已经介绍过Lucene了,这里就不多做介绍。
一、中文分词的原理
中文分词是将一个汉字序列切分为一个一个单独的词。分词就是讲连续的字序列安装一定的规范重新组合成词序列的过程。随着机器学习的发展,很多分词的方法都已经被科研人员实现,也越来越精确。分词的精确性一定程度上影响了搜索引擎的查全率与查准率,当然这是在你的中文分词运用在搜索引擎的前提之下。
分词的算法可以分为:基于字符串匹配的分词方法、基于统计的分词方法,很容易理解基于字符串匹配的分词方法有很大的局限性,很难做到准确的分词,因为世界上没有一本最完备的词典,很多专业词汇、人名巴拉巴拉之类很难涉及到。因此显而易见,基于统计的分词方法要更精确同时更复杂。
基于字符串匹配的分词方法又有:正向最大匹配、逆向最大匹配、最少切分等等方法
基于统计的分词方法很大程度上是根据上下文中,相邻的字同时出现的次数,字与字相邻共现的频率之类信息来实现更精确的分词,需要用到统计语言模型,设计很多数学原理,这里就不做更多介绍了,网上有很多资料。
二、关于停用词
停用词是自然语言中关键的组成,对于语义的构成有重要的意义,但是很多时候我们在做搜索是只需要内容的关键词而不是全部词,所以去除停用词是很必要的操作。例如汉语中的:“的”“是”等。
网上有一些汉语中常用停用词的整理,我使用的是GitHub上的一个停用词表。
三、代码实现
环境是Lucene4.6
import [图片]java.io.BufferedReader;
import [图片]java.io.File;
import [图片]java.io.FileInputStream;
import [图片]java.io.IOException;
import [图片]java.io.InputStreamReader;
import [图片]java.io.StringReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import [图片]org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
//import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.util.CharArraySet;
import org.apache.lucene.util.Version;
public class SegWordTest {
//创建一个去除停用词的分析器对象
public static CharArraySet stopwords = new CharArraySet(Version.LUCENE_46, 3, false);
public static Analyzer noStopAnalyzer;
public static void initializeData() throws IOException{
//读取停用词表格
File filename = new File("someFiles/stopwords.txt");
InputStreamReader reader = new InputStreamReader(new FileInputStream(filename));
BufferedReader br = new BufferedReader(reader);
String line = "";
line = br.readLine();
while(line != null){
stopwords.add(line);
line = br.readLine();
}
br.close();
noStopAnalyzer = new SmartChineseAnalyzer(Version.LUCENE_46, stopwords);
}
public static void testAnanlyzer(String cont) throws IOException{
/*
//不去除停用词的版本
//创建一个中文分词的分析器对象
Analyzer analyzer = new SmartChineseAnalyzer(Version.LUCENE_46);
//从分析器对象中获得tokenStream对象
TokenStream tokenStream = analyzer.tokenStream("myfield", new StringReader(cont));
*/
TokenStream tokenStream = noStopAnalyzer.tokenStream("myfield", new StringReader(cont));
//设置一个引用,这个引用可以使多种类型,可以是关键词的引用,偏移量的引用等等
//关键词的引用
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
//偏移量的引用,可以得到词汇开始和结束的位置
//OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
tokenStream.reset(); //很关键,不然会报错
while(tokenStream.incrementToken()){
System.out.println(charTermAttribute);
}
tokenStream.close();
}
public static void main(String args[]) throws IOException{
initializeData();
String con = "这是一架高空高速飞行的飞机";
testAnanlyzer(con);
}
}