`

Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息

阅读更多

Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息

在此回复牛妞的关于程序中分词器的问题,其实可以直接很简单的在词库中配置就好了,Lucene中分词的所有信息我们都可以从TokenStream流中获取.

分词器的核心类Analyzer,TokenStream,Tokenizer,TokenFilter.

Analyzer

Lucene中的分词器有StandardAnalyzer,StopAnalyzer,SimpleAnalyzer,WhitespaceAnalyzer.

TokenStream

分词器做好处理之后得到的一个流,这个流中存储了分词的各种信息.可以通过TokenStream有效的获取到分词单元

Tokenizer

主要负责接收字符流Reader,将Reader进行分词操作.有如下一些实现类

KeywordTokenizer,

standardTokenizer,

CharTokenizer

|----WhitespaceTokenizer

|----LetterTokenizer

|----LowerCaseTokenizer

TokenFilter

将分好词的语汇单元进行各种各样的过滤.

查看分词器的分词信息

 

package com.icreate.analyzer.luence;

import java.io.IOException;
import java.io.StringReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.util.Version;

/**
 *
 *  AnalyzerUtil.java   
 *
 *  @version : 1.1
 *  
 *  @author  : 苏若年    <a href="mailto:DennisIT@163.com">发送邮件</a>
 *    
 *  @since   : 1.0        创建时间:    2013-4-14  上午11:05:45
 *     
 *  TODO     : 
 *
 */
public class AnalyzerUtil {

    /**
     *
     * Description:         查看分词信息
     * @param str        待分词的字符串
     * @param analyzer    分词器
     *
     */
    public static void displayToken(String str,Analyzer analyzer){
        try {
            //将一个字符串创建成Token流
            TokenStream stream  = analyzer.tokenStream("", new StringReader(str));
            //保存相应词汇
            CharTermAttribute cta = stream.addAttribute(CharTermAttribute.class);
            while(stream.incrementToken()){
                System.out.print("[" + cta + "]");
            }
            System.out.println();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        Analyzer aly1 = new StandardAnalyzer(Version.LUCENE_36);
        Analyzer aly2 = new StopAnalyzer(Version.LUCENE_36);
        Analyzer aly3 = new SimpleAnalyzer(Version.LUCENE_36);
        Analyzer aly4 = new WhitespaceAnalyzer(Version.LUCENE_36);
        
        String str = "hello kim,I am dennisit,我是 中国人,my email is dennisit@163.com, and my QQ is 1325103287";
        
        AnalyzerUtil.displayToken(str, aly1);
        AnalyzerUtil.displayToken(str, aly2);
        AnalyzerUtil.displayToken(str, aly3);
        AnalyzerUtil.displayToken(str, aly4);
    }
}

 程序执行结果

 

 

[hello][kim][i][am][dennisit][我][是][中][国][人][my][email][dennisit][163][com][my][qq][1325103287]
[hello][kim][i][am][dennisit][我是][中国人][my][email][dennisit][com][my][qq]
[hello][kim][i][am][dennisit][我是][中国人][my][email][is][dennisit][com][and][my][qq][is]
[hello][kim,I][am][dennisit,我是][中国人,my][email][is][dennisit@163.com,][and][my][QQ][is][1325103287]

 

 

standardanalyzer将数字作为一个整体,每个单词都进行分隔

stopanalyzer将数字停用 中文不起作用,只坐空格分割

simpleanalyzer将数字停用 中文不起作用,只按照空格分割

whitespaceanalyzer按照空格分隔,中文不起作用

展示分词的详细信息

 

 

/**
     * 
     * Description:        显示分词的全部信息
     * @param str
     * @param analyzer
     *
     */
    public static void displayAllTokenInfo(String str, Analyzer analyzer){
        try {
            //第一个参数只是标识性没有实际作用
            TokenStream stream = analyzer.tokenStream("", new StringReader(str));
            //获取词与词之间的位置增量
            PositionIncrementAttribute postiona = stream.addAttribute(PositionIncrementAttribute.class);
            //获取各个单词之间的偏移量
            OffsetAttribute offseta = stream.addAttribute(OffsetAttribute.class);
            //获取每个单词信息
            CharTermAttribute chara = stream.addAttribute(CharTermAttribute.class);
            //获取当前分词的类型
            TypeAttribute typea = stream.addAttribute(TypeAttribute.class);
            while(stream.incrementToken()){
                System.out.print("位置增量" +postiona.getPositionIncrement()+":\t");
                System.out.println(chara+"\t[" + offseta.startOffset()+" - " + offseta.endOffset() + "]\t<" + typea +">");
            }
            System.out.println();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

 

测试代码

        Analyzer aly1 = new StandardAnalyzer(Version.LUCENE_36);
        Analyzer aly2 = new StopAnalyzer(Version.LUCENE_36);
        Analyzer aly3 = new SimpleAnalyzer(Version.LUCENE_36);
        Analyzer aly4 = new WhitespaceAnalyzer(Version.LUCENE_36);
        
        String str = "hello kim,I am dennisit,我是 中国人,my email is dennisit@163.com, and my QQ is 1325103287";
        
        AnalyzerUtil.displayAllTokenInfo(str, aly1);
        AnalyzerUtil.displayAllTokenInfo(str, aly2);
        AnalyzerUtil.displayAllTokenInfo(str, aly3);
        AnalyzerUtil.displayAllTokenInfo(str, aly4);

 程序运行结果

位置增量1:    hello    [0 - 5]    <type=<ALPHANUM>>
位置增量1:    kim    [6 - 9]    <type=<ALPHANUM>>
位置增量1:    i    [10 - 11]    <type=<ALPHANUM>>
位置增量1:    am    [12 - 14]    <type=<ALPHANUM>>
位置增量1:    dennisit    [15 - 23]    <type=<ALPHANUM>>
位置增量1:    我    [24 - 25]    <type=<IDEOGRAPHIC>>
位置增量1:    是    [25 - 26]    <type=<IDEOGRAPHIC>>
位置增量1:    中    [27 - 28]    <type=<IDEOGRAPHIC>>
位置增量1:    国    [28 - 29]    <type=<IDEOGRAPHIC>>
位置增量1:    人    [29 - 30]    <type=<IDEOGRAPHIC>>
位置增量1:    my    [31 - 33]    <type=<ALPHANUM>>
位置增量1:    email    [34 - 39]    <type=<ALPHANUM>>
位置增量2:    dennisit    [43 - 51]    <type=<ALPHANUM>>
位置增量1:    163    [52 - 55]    <type=<NUM>>
位置增量1:    com    [56 - 59]    <type=<ALPHANUM>>
位置增量2:    my    [65 - 67]    <type=<ALPHANUM>>
位置增量1:    qq    [68 - 70]    <type=<ALPHANUM>>
位置增量2:    1325103287    [74 - 84]    <type=<NUM>>

位置增量1:    hello    [0 - 5]    <type=word>
位置增量1:    kim    [6 - 9]    <type=word>
位置增量1:    i    [10 - 11]    <type=word>
位置增量1:    am    [12 - 14]    <type=word>
位置增量1:    dennisit    [15 - 23]    <type=word>
位置增量1:    我是    [24 - 26]    <type=word>
位置增量1:    中国人    [27 - 30]    <type=word>
位置增量1:    my    [31 - 33]    <type=word>
位置增量1:    email    [34 - 39]    <type=word>
位置增量2:    dennisit    [43 - 51]    <type=word>
位置增量1:    com    [56 - 59]    <type=word>
位置增量2:    my    [65 - 67]    <type=word>
位置增量1:    qq    [68 - 70]    <type=word>

位置增量1:    hello    [0 - 5]    <type=word>
位置增量1:    kim    [6 - 9]    <type=word>
位置增量1:    i    [10 - 11]    <type=word>
位置增量1:    am    [12 - 14]    <type=word>
位置增量1:    dennisit    [15 - 23]    <type=word>
位置增量1:    我是    [24 - 26]    <type=word>
位置增量1:    中国人    [27 - 30]    <type=word>
位置增量1:    my    [31 - 33]    <type=word>
位置增量1:    email    [34 - 39]    <type=word>
位置增量1:    is    [40 - 42]    <type=word>
位置增量1:    dennisit    [43 - 51]    <type=word>
位置增量1:    com    [56 - 59]    <type=word>
位置增量1:    and    [61 - 64]    <type=word>
位置增量1:    my    [65 - 67]    <type=word>
位置增量1:    qq    [68 - 70]    <type=word>
位置增量1:    is    [71 - 73]    <type=word>

位置增量1:    hello    [0 - 5]    <type=word>
位置增量1:    kim,I    [6 - 11]    <type=word>
位置增量1:    am    [12 - 14]    <type=word>
位置增量1:    dennisit,我是    [15 - 26]    <type=word>
位置增量1:    中国人,my    [27 - 33]    <type=word>
位置增量1:    email    [34 - 39]    <type=word>
位置增量1:    is    [40 - 42]    <type=word>
位置增量1:    dennisit@163.com,    [43 - 60]    <type=word>
位置增量1:    and    [61 - 64]    <type=word>
位置增量1:    my    [65 - 67]    <type=word>
位置增量1:    QQ    [68 - 70]    <type=word>
位置增量1:    is    [71 - 73]    <type=word>
位置增量1:    1325103287    [74 - 84]    <type=word>

 

自定义stop分词器

继承Analyzer复写public TokenStream tokenStream(String filename,Reader reader)方法

package org.dennisit.lucene.util;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Set;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.LetterTokenizer;
import org.apache.lucene.analysis.LowerCaseFilter;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.analysis.StopFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.util.Version;

/**
 *
 *  org.dennisit.lucene.utilMyStopAnalyzer.java   
 *
 *  @version : 1.1
 *  
 *  @author  : 苏若年         <a href="mailto:DennisIT@163.com">发送邮件</a>
 *    
 *  @since   : 1.0      创建时间:    2013-4-14  下午12:06:08
 *     
 *  TODO     : 
 *
 */
public class MyStopAnalyzer extends Analyzer{
    
    private Set stops;
    
    /**
     * 在原来停用词基础上增加自己的停用词
     * @param stopwords    自定义停用词采用数组传递
     */
    public MyStopAnalyzer(String[] stopwords){
        //会自动将字符串数组转换为Set
        stops = StopFilter.makeStopSet(Version.LUCENE_36,stopwords,true);
        //将原有的停用词加入到现在的停用词
        stops.addAll(StopAnalyzer.ENGLISH_STOP_WORDS_SET);
    }
    
    /**
     * 不传入参数表示使用原来默认的停用词
     */
    public MyStopAnalyzer(){
        //获取原有的停用词
        stops = StopAnalyzer.ENGLISH_STOP_WORDS_SET;
    }
    
    @Override
    public TokenStream tokenStream(String filename,Reader reader){
        //为自定义分词器设定过滤链和Tokenizer
        return  new StopFilter(Version.LUCENE_36, 
                new LowerCaseFilter(Version.LUCENE_36, 
                new LetterTokenizer(Version.LUCENE_36,reader)),
                stops);
    }
    
    
    /**
     *
     * Description:         查看分词信息
     * @param str        待分词的字符串
     * @param analyzer    分词器
     *
     */
    public static void displayToken(String str,Analyzer analyzer){
        try {
            //将一个字符串创建成Token流
            TokenStream stream  = analyzer.tokenStream("", new StringReader(str));
            //保存相应词汇
            CharTermAttribute cta = stream.addAttribute(CharTermAttribute.class);
            while(stream.incrementToken()){
                System.out.print("[" + cta + "]");
            }
            System.out.println();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        //获取原来的停用词
        Analyzer myAnalyzer1 = new MyStopAnalyzer();
        //追加自己的停用词
        Analyzer myAnalyzer2 = new MyStopAnalyzer(new String[]{"hate","fuck"});
        //分词处理的句子
        String text = "fuck! I hate you very much";
        
        displayToken(text, myAnalyzer1);
        displayToken(text, myAnalyzer2);
    }
}

 

程序运行结果

[fuck][i][hate][you][very][much]
[i][you][very][much]

 

分享到:
评论

相关推荐

    MMAnalyzer 分词jar包(lucene-core-2.4.1.jar je-analysis-1.5.3.jar)

    例如,可以创建一个Analyzer实例,设置分词参数,接着使用TokenStream来处理文本,最后遍历TokenStream获取分词结果。 在实际应用中,开发者可能会遇到一些挑战,比如如何处理未登录词(不在词典中的词汇)、如何...

    lucene-highlighter-2.2.0-src.zip

    《深入解析Lucene高亮显示源码:剖析`lucene-highlighter-2.2.0-src.zip`》 Lucene,作为一个开源全文检索库,以其高效、灵活的特点在信息检索领域广泛应用。在处理搜索结果时,为了提升用户体验,通常会采用高亮...

    lucene-analyzers-3.3.0 jar包和源码

    《深入理解Lucene-Analyzers-3.3.0:jar包与源码...通过深入学习和实践,我们可以更好地利用Lucene来构建高效、精准的全文检索系统,满足各种复杂的应用场景。无论是初学者还是经验丰富的开发者,都能从中受益匪浅。

    Lucene4.X实战类baidu搜索的大型文档海量搜索系统-22.Lucene分词器3 共4页.pptx

    在这个系列中,我们特别关注了Lucene的分词器,尤其是第三部分——"Lucene分词器3"。 Lucene作为一款强大的全文搜索引擎库,其核心功能之一就是对输入的文本进行有效的分词处理,以便于后续的索引和搜索操作。分词...

    Lucene.Net-2.9.2 c#源码

    1. 分词器(Tokenizer):分词器是Lucene处理文本的第一步,负责将输入的字符串分解为一系列的词元(Token)。Lucene.Net包含多种预定义的分词器,如StandardAnalyzer用于英文,而ChineseAnalyzer适用于中文。 2. ...

    Lucene5学习之自定义同义词分词器简单示例

    总之,自定义Lucene分词器,尤其是添加同义词处理,是一项增强搜索质量和用户体验的关键技术。通过这个简单的示例,我们可以了解如何结合源码和工具来实现这一目标。在阅读给定的博文链接(已提供但不可访问)时,你...

    Java日文分词器之Kuromoji

    Java日文分词器Kuromoji是一款强大的自然语言处理工具,主要用于日语文本的分词。在IT领域,尤其是在信息检索、文本分析和自然语言处理应用中,分词是基础且关键的一环。Kuromoji是基于Apache Lucene项目开发的,它...

    分词器LUcene

    《深入理解Lucene分词器:歧义处理与数量词合并》 在信息检索和自然语言处理领域,分词是至关重要的第一步。Lucene,作为Java最著名的全文搜索引擎库,其强大的分词能力使得它在各种信息检索系统中广泛应用。本文将...

    运用在lucene中的中文分词算法源码

    《深入剖析Lucene中的中文分词算法源码》 在信息检索领域,Lucene作为一款强大的全文搜索引擎库,被...通过深入学习这些分词器的工作原理,开发者可以更好地调整分词策略,以适应特定的应用场景,提升系统的整体性能。

    Lucene 3.6 学习笔记

    【Lucene 3.6 学习笔记】 Lucene 是一个高性能、全文本搜索库,广泛应用于各种搜索引擎的开发。本文将深入探讨Lucene 3.6...通过学习这些内容,可以深入理解Lucene的工作机制,并利用其强大的搜索能力构建高效的应用。

    lucene-solr-4.7所有Jar包 tika包 IK包 mmseg4j包

    lucene-solr-4.7所有Jar包 tika包 IK包 mmseg4j包 包括索引、高亮、IK分词及MMSEG分词 其中MMSEG中的BUG: TokenStream contract violation: reset()/close() call missing, reset() called multiple times, or ...

    IKAnalyzer和Lucene分词工具下载地址+使用方法

    在这个例子中,我们创建了`IKAnalyzer`对象,并通过`tokenStream()`方法获取分词流,然后遍历流中的每个分词,打印出分词结果。 **应用场景** IKAnalyzer和Lucene的组合广泛应用于各种需要中文分词的场景,如: -...

    Lucene使用

    Exception in thread "main" java.lang.AbstractMethodError: org.apache.lucene.analysis.TokenStream.incrementToken()Z 换用svn里源码版正常 http://paoding.googlecode.com/svn/trunk/paoding-analysis/

    盘古分词、lucene3.0.3搜索的使用示例.zip

    2. **创建索引**:利用Lucene提供的Analyzer接口,我们可以自定义分词器,将盘古分词集成进来。创建一个继承自Analyzer的类,覆写TokenStream方法,调用盘古分词的API进行分词,然后返回TokenStream。 3. **文档...

    Lucene分词与查询详解

    **Lucene分词与查询详解** Lucene是一个高性能、全文本搜索库,广泛应用于各种搜索引擎的开发中。它提供了一套强大的API,用于索引文本数据,并执行复杂的查询操作。在深入理解Lucene的分词与查询机制之前,我们...

    lucene中文分词源码,做搜索引擎需要用到的好东西哦

    《深入理解Lucene中文分词源码:打造高效搜索引擎》 在信息爆炸的时代,搜索引擎已经成为了我们获取知识的重要工具。而构建一个强大的搜索引擎,离不开核心的文本处理技术——中文分词。Lucene作为一款高性能、全文...

    Lucene如何使用TokenFilter进行再分词

    本文将详细介绍如何使用`TokenFilter`进行再分词,并结合提供的源代码进行解析。 首先,理解Lucene的分词流程至关重要。当处理一个文档时,我们首先使用`Tokenizer`将文本切割成一系列的“令牌”(tokens),这些...

    全文检索技术学习(三)——Lucene支持中文分词 - 李阿昀的博客 - CSDN博客1

    在全文检索技术中,Lucene 是一个非常重要的开源搜索引擎库,它提供了强大的文本分析和索引功能。...理解 Analyzer 的工作原理以及如何定制和使用 Analyzer 是深入学习 Lucene 全文检索技术的关键。

    lucene分词程序

    《深入理解Lucene分词程序》 在信息技术领域,搜索引擎的构建是不可或缺的一部分,而Lucene作为开源全文检索库,为开发者提供了强大的文本检索功能。本文将深入探讨如何利用Java编程语言来添加自定义的分词程序到...

    IK分词器源码

    深入研究IK分词器的源码,不仅可以了解中文分词的基本原理,还能掌握如何利用词典和算法优化分词效果,对于从事信息检索、自然语言处理以及相关领域的开发者来说,具有很高的学习价值。同时,熟悉源码也有助于在遇到...

Global site tag (gtag.js) - Google Analytics