Lucene分词器详解

一、分词器作用

  • 在创建索引的时候需要用到分词器,在使用字符串搜索的时候也会用到分词器,并且这两个地方要使用同一个分词器,否则可能会搜索不出来结果。

  • 分词器(Analyzer)的作用是把一段文本中的词按规则取出所包含的所有词,对应的是Analyzer类,这是一个抽象类(public abstract class org.apache.lucene.analysis.Analyzer),切分词的具体规则是由子类实现的,所以对于不同的语言规则,要有不同的分词器。

二、分词器原理

分词器分为中文分词器和英文分词器:

英文分词器是按照词汇切分,同时做词干提取,也就是将单词末尾的变化还原,使其能搜索出来(例如输入boy,能搜索出boys),另外各种分词器对英文都支持的比较好。

中文分词器有很多实现方式,实现原理基本差不多,都是Analyzer的子类:

  • 标准分词器:也叫单字分词,将中文一个字一个字的分词。
  • 简单分词器:根据标点符号进行分词。
  • 二分法分词器:按照两个字进行分词。
  • 停用词分词器:和简单分词器很像,根据被忽略停用的词(比如标点符号)进行分词。
  • 空格分词器:根据空格进行分词
  • IK中文分词器:分为两种实现,一种是采用智能切分,另一种是最细粒度切分算法。

Lucene自带的分词器对中文分词的效果不是很理想,IKAnalyzer分词器是由他人自定义编写的分析器,最新版本为2012年的版本,支持lucene4.0。后续Lucene版本接口改变使其不能支持,所以要用IK分词器,智能修改其源码,或者降低Lucene版本

三、代码示例

本文代码示例IK分词器为Lucene4.0版本,其余分词器对应Lucene版本为5.3.1

public static void display(String str, Analyzer a) {
        TokenStream stream = null ;
        try {
            stream = a.tokenStream( "renyi", new StringReader(str)) ;
            PositionIncrementAttribute pia = stream.addAttribute(PositionIncrementAttribute.class ) ;  //保存位置
            OffsetAttribute oa = stream.addAttribute(OffsetAttribute.class ) ; //保存辞与词之间偏移量
            CharTermAttribute cta = stream.addAttribute(CharTermAttribute.class ) ;//保存响应词汇
            TypeAttribute ta = stream.addAttribute(TypeAttribute.class ) ; //保存类型
            //在lucene 4 以上  要加入reset 和  end方法
            stream.reset() ;
            while (stream.incrementToken()) {
                System. out.println(pia.getPositionIncrement() + ":[" + cta.toString() + "]:" + oa.startOffset() + "->" + oa.endOffset() + ":" + ta.type());
            }
            stream.end() ;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
public static void main(String[] args) {
        String str = "我是Lucene 分词器,查看分词情况" ;
        Analyzer a = new StandardAnalyzer() ;      //标准分词器
        Analyzer b = new SimpleAnalyzer() ;        //简单分词器
        Analyzer c = new StopAnalyzer() ;          //停用词分词器
        Analyzer d = new WhitespaceAnalyzer() ; //空格分词器
        Analyzer f = new CJKAnalyzer();//二分法分词器
        display(str,a) ;
        System. out.println( "-----------------------------");
        display(str,b) ;
        System. out.println( "-----------------------------");
        display(str,c) ;
        System. out.println( "-----------------------------");
        display(str,d) ;
        System. out.println( "-----------------------------");
        display(str,f) ;
        System. out.println( "-----------------------------");
    }

IK分词器代码示例

public static List<String> getAnalyzedStr(Analyzer analyzer, String content) throws Exception {
		TokenStream stream = analyzer.tokenStream(null, new StringReader(content));
		CharTermAttribute term = stream.addAttribute(CharTermAttribute.class);

		List<String> result = new ArrayList<String>();
		while (stream.incrementToken()) {
			result.add(term.toString());
		}

		return result;
	}
public static void testAnalyzer(String content) throws Exception {
		Analyzer analyzer = new IKAnalyzer(); // 等于new IKAnalyzer(false);
		System.out.println("new IKAnalyzer()解析输出:" + getAnalyzedStr(analyzer, content));

		analyzer = new IKAnalyzer(true);
		System.out.println("new IKAnalyzer(true)解析输出:" + getAnalyzedStr(analyzer, content));
	}
public static void main(String[] args) throws Exception {
		String content = "我是Lucene 分词器,查看分词情况";

		System.out.println("原文:" + content);
		testAnalyzer(content);
	}

各分词器分词比较

1:[我]:0->1:<IDEOGRAPHIC>
1:[是]:1->2:<IDEOGRAPHIC>
1:[lucene]:2->8:<ALPHANUM>
1:[分]:9->10:<IDEOGRAPHIC>
1:[词]:10->11:<IDEOGRAPHIC>
1:[器]:11->12:<IDEOGRAPHIC>
1:[查]:13->14:<IDEOGRAPHIC>
1:[看]:14->15:<IDEOGRAPHIC>
1:[分]:15->16:<IDEOGRAPHIC>
1:[词]:16->17:<IDEOGRAPHIC>
1:[情]:17->18:<IDEOGRAPHIC>
1:[况]:18->19:<IDEOGRAPHIC>
-----------------------------
1:[我是lucene]:0->8:word
1:[分词器]:9->12:word
1:[查看分词情况]:13->19:word
-----------------------------
1:[我是lucene]:0->8:word
1:[分词器]:9->12:word
1:[查看分词情况]:13->19:word
-----------------------------
1:[我是Lucene]:0->8:word
1:[分词器,查看分词情况]:9->19:word
-----------------------------
1:[我是]:0->2:<DOUBLE>
1:[lucene]:2->8:<ALPHANUM>
1:[分词]:9->11:<DOUBLE>
1:[词器]:10->12:<DOUBLE>
1:[查看]:13->15:<DOUBLE>
1:[看分]:14->16:<DOUBLE>
1:[分词]:15->17:<DOUBLE>
1:[词情]:16->18:<DOUBLE>
1:[情况]:17->19:<DOUBLE>
-----------------------------
原文:我是Lucene 分词器,查看分词情况
new IKAnalyzer()解析输出:[我, 是, lucene, 分词器, 分词, 器, 查看, 分词, 情况]
new IKAnalyzer(true)解析输出:[我, 是, lucene, 分词器, 查看, 分词, 情况]
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值