本文转载http://blog.csdn.net/jspamd/article/details/8194919

  不同的Lucene分析器Analyzer,它对TokenStream进行分词的方法是不同的,这需要根据具体的语言来选择。比如英文,一般是通过空格来分割词条,而中文汉字则不能通过这种方式,最简单的方式就是单个汉字作为一个词条。

TokenStream是通过从设备或者其他地方获取数据源而构造的一个流,我们要执行分词的动作,应该对这个TokenStream进行操作。

TokenStream也可以不是直接通过数据源构造的流,可以是经过分词操作之后读入TokenFilter的一个分词流。

从本地磁盘的文件读取文本内容,假定在文本文件shirdrn.txt中有下列文字:

中秋之夜,享受着月华的孤独,享受着爆炸式的思维跃迁。

通过使用FileReader构造一个流,对其进行分词:

package org.shirdrn.lucene;

import java.io.File;
import java.io.FileReader;
import java.io.Reader; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer; public class MyAnalyzer { public static void main(String[] args) {
try {
File file = new File("E:\\shirdrn.txt");
Reader reader = new FileReader(file);
Analyzer a = new StandardAnalyzer();
//Analyzer a = new CJKAnalyzer();
//Analyzer a = new ChineseAnalyzer();
//Analyzer a = new WhitespaceAnalyzer();
TokenStream ts = a.tokenStream("", reader);
Token t = null;
int n = 0;
while((t = ts.next()) != null ){
n ++ ;
System.out.println("词条"+n+"的内容为 :"+t.termText());
}
System.out.println("== 共有词条 "+n+" 条 ==");
} catch (Exception e) {
e.printStackTrace();
}
}
}

这里使用StandardAnalyzer分析器,而且使用了不带参数的构造器StandardAnalyzer(),在StandardAnalyzer类的这个不带参数的构造器中,指定了一个过滤字符数组STOP_WORDS:

public StandardAnalyzer() {
this(STOP_WORDS);
}

而在StandardAnalyzer类中定义的STOP_WORDS 数组实际是引用StopAnalyzer类的ENGLISH_STOP_WORDS数组,该数组中可以根据需要添加过滤的字符:

public static final String[] STOP_WORDS = StopAnalyzer.ENGLISH_STOP_WORDS;

StopAnalyzer类中ENGLISH_STOP_WORDS数组原始内容如下所示:

public static final String[] ENGLISH_STOP_WORDS = {
"a", "an", "and", "are", "as", "at", "be", "but", "by",
"for", "if", "in", "into", "is", "it",
"no", "not", "of", "on", "or", "such",
"that", "the", "their", "then", "there", "these",
"they", "this", "to", "was", "will", "with"
};

都是一些英文单词,而且这些单词对于检索关键字意义不大,所以在分析的时候应该把出现的这些单词过滤掉。

如果按照默认的STOP_WORDS运行上面我们的测试程序,则根本没有对中文起到过滤作用,测试结果如下所示:

词条1的内容为 :中
词条2的内容为 :秋
词条3的内容为 :之
词条4的内容为 :夜
词条5的内容为 :享
词条6的内容为 :受
词条7的内容为 :着
词条8的内容为 :月
词条9的内容为 :华
词条10的内容为 :的
词条11的内容为 :孤
词条12的内容为 :独
词条13的内容为 :享
词条14的内容为 :受
词条15的内容为 :着
词条16的内容为 :爆
词条17的内容为 :炸
词条18的内容为 :式
词条19的内容为 :的
词条20的内容为 :思
词条21的内容为 :维
词条22的内容为 :跃
词条23的内容为 :迁
== 共有词条 23 条 ==

我们可以在org.apache.lucene.analysis.StopAnalyzer类中定制自己的STOP_WORDS,例如我们定义:

public static final String[] ENGLISH_STOP_WORDS = {
"着", "的", "之", "式"
};

则再执行上面的测试程序,分词过程中会过滤掉出现在ENGLISH_STOP_WORDS数组中的词条,如下所示:

词条1的内容为 :中
词条2的内容为 :秋
词条3的内容为 :夜
词条4的内容为 :享
词条5的内容为 :受
词条6的内容为 :月
词条7的内容为 :华
词条8的内容为 :孤
词条9的内容为 :独
词条10的内容为 :享
词条11的内容为 :受
词条12的内容为 :爆
词条13的内容为 :炸
词条14的内容为 :思
词条15的内容为 :维
词条16的内容为 :跃
词条17的内容为 :迁
== 共有词条 17 条 ==

另外,因为StandardAnalyzer类具有很多带参数的构造函数,可以在实例化一个StandardAnalyzer的时候,通过构造函数定制分析器,例如使用:

public StandardAnalyzer(Set stopWords)

构造的分析器如下:

   Set stopWords = new HashSet();
stopWords.add("着");
stopWords.add("的");
stopWords.add("之");
stopWords.add("式");
Analyzer a = new StandardAnalyzer(stopWords);

运行结果同修改StopAnalyzer类中的STOP_WORDS结果是一样的。

还有一个构造函数,通过使用数组指定stopWords的过滤词条:

public StandardAnalyzer(String[] stopWords) {
stopSet = StopFilter.makeStopSet(stopWords);
}

调用了StopFilter类的makeStopSet方法对stopWords中的字符进行了转换处理:

public static final Set makeStopSet(String[] stopWords) {
return makeStopSet(stopWords, false);
}

又调用了该类的一个重载的方法makeStopSet,第一个参数指定过滤词条的数组,第一个参数为boolean类型,设置是否要将大写字符转换为小写:

public static final Set makeStopSet(String[] stopWords, boolean ignoreCase) {
HashSet stopTable = new HashSet(stopWords.length);
for (int i = 0; i < stopWords.length; i++)
stopTable.add(ignoreCase ? stopWords[i].toLowerCase() : stopWords[i]);
return stopTable;
}

在StandardAnalyzer类中,没有把stopWords中的词条转换为小写。

上面的三种构造StandardAnalyzer分析器的方式都是在程序中指定要过滤词条,程序的独立性比较差,因为每次想要添加过滤词条都需要改动程序。

StandardAnalyzer还提供了两种从数据源读取过滤词条的文本的构造方式:

public StandardAnalyzer(File stopwords) throws IOException {
stopSet = WordlistLoader.getWordSet(stopwords);
} public StandardAnalyzer(Reader stopwords) throws IOException {
stopSet = WordlistLoader.getWordSet(stopwords);
}

他们分别使用File和Reader分别来构造一个File对象和读取字符流,从指定的数据源读取内容,然后调用WordlistLoader类的getWordSet静态方法来对读取的字符流进行转换操作,以从File对象中获取字符为例:

public static HashSet getWordSet(File wordfile) throws IOException {
HashSet result = new HashSet();
FileReader reader = null;
try {
reader = new FileReader(wordfile);
result = getWordSet(reader);
}
finally {
if (reader != null)
reader.close();
}
return result;
}

实际上仍然通过File对象构造一个FileReader读取字符流,然后从流中取得过滤的词条,加入到HashSet 中。这里调用了获取HashSet的getWordSet方法,在方法getWordSet中才真正地实现了提取词条的操作:

public static HashSet getWordSet(Reader reader) throws IOException {
HashSet result = new HashSet();
BufferedReader br = null;
try {
if (reader instanceof BufferedReader) {
br = (BufferedReader) reader;
} else {
br = new BufferedReader(reader);
}
String word = null;
while ((word = br.readLine()) != null) {
result.add(word.trim());
}
}
finally {
if (br != null)
br.close();
}
return result;
}

这里提取词条要求读入的文本是按照行来分割过滤词条的,即每行作为一个词条。对于中文,只能是每个字作为一行,如果以两个的词语作为一行,处理后根本没有加入到过滤词条的HashSet中,这时因为StandardAnalyzer分析器是以单个中文汉字作为一个词条的。我们可以定制自己的分析器。

测试一下上述说明的情况。

在本地磁盘上建立一个txt文本stopWords.txt,添加过滤词条:




测试程序如下所示:

   public static void main(String[] args) {
try {
File file = new File("E:\\shirdrn.txt");
FileReader stopWords = new FileReader("E:\\stopWords.txt");
Reader reader = new FileReader(file);
Analyzer a = new StandardAnalyzer(stopWords);
TokenStream ts = a.tokenStream("", reader);
Token t = null;
int n = 0;
while((t = ts.next()) != null ){
n ++ ;
System.out.println("词条"+n+"的内容为 :"+t.termText());
}
System.out.println("== 共有词条 "+n+" 条 =="); } catch (Exception e) {
e.printStackTrace();
}
}

测试输出结果同前面的一样,都对词条进行了过滤:

词条1的内容为 :中
词条2的内容为 :秋
词条3的内容为 :夜
词条4的内容为 :享
词条5的内容为 :受
词条6的内容为 :月
词条7的内容为 :华
词条8的内容为 :孤
词条9的内容为 :独
词条10的内容为 :享
词条11的内容为 :受
词条12的内容为 :爆
词条13的内容为 :炸
词条14的内容为 :思
词条15的内容为 :维
词条16的内容为 :跃
词条17的内容为 :迁
== 共有词条 17 条 ==

通过lucene的StandardAnalyzer分析器来了解分词的更多相关文章

  1. Lucene.net(4.8.0)+PanGu分词器问题记录一:分词器Analyzer的构造和内部成员ReuseStategy

    前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...

  2. Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考

    前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...

  3. Lucene基础(三)-- 中文分词及高亮显示

    Lucene分词器及高亮 分词器 在lucene中我们按照分词方式把文档进行索引,不同的分词器索引的效果不太一样,之前的例子使用的都是标准分词器,对于英文的效果很好,但是中文分词效果就不怎么样,他会按 ...

  4. Lucene为不同字段指定不同分词器(转)

    在lucene使用过程中,如果要对同一IndexWriter中不同 Document,不同Field中使用不同的analyzer,我们该如何实现呢? 通过对<lucene in action&g ...

  5. 查看分析器(Analyzer)的分词效果

    1 测试代码 package com.test.lucene.helloworld; import org.apache.lucene.analysis.Analyzer; import org.ap ...

  6. 【lucene系列学习四】使用IKAnalyzer分词器实现敏感词和停用词过滤

    Lucene自带的中文分词器SmartChineseAnalyzer不太好扩展,于是我用了IKAnalyzer来进行敏感词和停用词的过滤. 首先,下载IKAnalyzer,我下载了 然后,由于IKAn ...

  7. Lucene 6.0下使用IK分词器

    Lucene 6.0使用IK分词器需要修改修改IKAnalyzer和IKTokenizer. 使用时先新建一个MyIKTokenizer类,一个MyIkAnalyzer类: MyIKTokenizer ...

  8. 【netcore基础】.Net core通过 Lucene.Net 和 jieba.NET 处理分词搜索功能

    业务要求是对商品标题可以进行模糊搜索 例如用户输入了[我想查询下雅思托福考试],这里我们需要先将这句话分词成[查询][雅思][托福][考试],然后搜索包含相关词汇的商品. 思路如下 首先我们需要把数据 ...

  9. ElasticSearch自定义分析器-集成结巴分词插件

    关于结巴分词 ElasticSearch 插件: https://github.com/huaban/elasticsearch-analysis-jieba 该插件由huaban开发.支持Elast ...

随机推荐

  1. AC日记——字符替换 openjudge 1.7 08

    08:字符替换 总时间限制:  1000ms 内存限制:  65536kB 描述 把一个字符串中特定的字符全部用给定的字符替换,得到一个新的字符串. 输入 只有一行,由一个字符串和两个字符组成,中间用 ...

  2. 什么是UV?

    转自http://www.cnblogs.com/jenry/p/4083415.html 1.什么是UV?   对于三维模型,有两个最重要的坐标系统,一是顶点的位置(X,Y,Z)坐标,另一个就是UV ...

  3. js模拟高级语言的重载

    js以递归的方式模拟高级语言的重载,我以添加元素节点为例子: //现有的子元素之前插入一个新的子元素 var before = function(elem,newElement,targetEleme ...

  4. IOS-利用AFNetworking监听网络状态

    网络环境检测:检测用户当前所处的网络状态 效果图 1.当蜂窝和wifi同时关闭时候  显示为不可达(AFNetworkReachabilityStatusNotReachable)状态 2.打开蜂窝移 ...

  5. BZOJ 2957 楼房重建

    Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...

  6. BZOJ 1066 【SCOI2007】 蜥蜴

    Description 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为$1$,蜥蜴的跳跃距离是d,即蜥蜴可以跳 ...

  7. swift 随机生成背景颜色

    swift是一门新语言,相关的文档资料现在基本上还不是很完整.在尝试开发过程中,走了不少弯路.在这里记录一下自己的”路“,希望以后能少走弯路. 生成随机背景颜色使用的语法和C#或者JAVA基本一致. ...

  8. [JAVA教程] 2016年最新spring4框架搭建视频教程 【尚学堂】

    Spring4框架 主讲:邹波 类型:SSH 适合对象:学习完javase.数据库技术.jdbc者 Spring4.0作为一个广泛使用的开源框架,它由Rod Johnson创建.它是为了解决企业应用开 ...

  9. 跟我学习Storm_Storm基本概念

    首先我们通过一个Storm和Hadoop的对比来了解Storm中的基本概念. 接下来我们再来具体看一下这些概念. Nimbus:负责资源分配和任务调度. Supervisor:负责接受nimbus分配 ...

  10. 2013级软件工程GitHub账号信息

    GitHub账号信息 序号 班级 学号 姓名 个人GitHub网址 1 信1301-1班 20122951 刘伟 https://github.com/weige8882 2 信1301-1班 201 ...