`
444878909
  • 浏览: 639181 次
文章分类
社区版块
存档分类
最新评论

自己写Lucene分词器原理篇——CJKAnalyzer简单讲解

阅读更多

其中CJK中日韩统一表意文字(CJK Unified Ideographs),目的是要把分别来自中文、日文、韩文、越文中,本质、意义相同、形状一样或稍异的表意文字(主要为汉字,但也有仿汉字如日本国字、韩国独有汉字、越南的喃字)于ISO 10646及Unicode标准内赋予相同编码。CJK 是中文(Chinese)、日文(Japanese)、韩文(Korean)三国文字的缩写。顾名思义,它能够支持这三种文字。

实际上,CJKAnalyzer支持中文、日文、韩文和朝鲜文。

CJKAnalyzer的所有类:


CJKAnalyzer是主类

CJKWidthFilter是负责格式化字符,主要是折叠变种的半宽片假名成等价的假名

CJKBigramFilter是负责把两个CJK字符切割成两个,只要是CJK字符就会两两切割,ABC->AB,BC

CJKTokenizer是兼容低版本的分析器

1.CJKAnalyzer的主要部分,可以看出,先判断版本号,低版本直接用CJKTokenizer,高版本的先用standardanalyzer把非英文字母数字一个个分开,再用CJKWidthFilter格式化CJK字符,再用LowerCaseFilter转换英文成小写,再用CJKBigramFilter把CJK字符切割成两两的。

protected TokenStreamComponents createComponents(String fieldName,
      Reader reader) {
    if (matchVersion.onOrAfter(Version.LUCENE_36)) {
      final Tokenizer source = new StandardTokenizer(matchVersion, reader);
      // run the widthfilter first before bigramming, it sometimes combines characters.
      TokenStream result = new CJKWidthFilter(source);
      result = new LowerCaseFilter(matchVersion, result);
      result = new CJKBigramFilter(result);
      return new TokenStreamComponents(source, new StopFilter(matchVersion, result, stopwords));
    } else {
      final Tokenizer source = new CJKTokenizer(reader);
      return new TokenStreamComponents(source, new StopFilter(matchVersion, source, stopwords));
    }
  }
2.CJKWidthFilter的部分主要是折叠变种的半宽片假名成等价的假名,有点类似全角符号转换成半角符号,含义是一样的,但是表示不一样,主要针对日文。

3.CJKBigramFilter,该fileter可以选择既输出单字切割,同时也输出双字切割;或者只输出双字切割

public boolean incrementToken() throws IOException {
    while (true) {
    //判断之前是否暂存了双CJK字符 
       if (hasBufferedBigram()) {
        
        // case 1: we have multiple remaining codepoints buffered,
        // so we can emit a bigram here.
        //如果选择了要输出单字切割
        if (outputUnigrams) {

          // when also outputting unigrams, we output the unigram first,
          // then rewind back to revisit the bigram.
          // so an input of ABC is A + (rewind)AB + B + (rewind)BC + C
          // the logic in hasBufferedUnigram ensures we output the C, 
          // even though it did actually have adjacent CJK characters.

          if (ngramState) {
            flushBigram();//写双字
          } else {
            flushUnigram();//写单字,然后后退一个字符(rewind)
            index--;
          }
         //这个个对应上面的判断,实现双字输出
          ngramState = !ngramState;
        } else {
          flushBigram();
        }
        return true;
      } else if (doNext()) {

        // case 2: look at the token type. should we form any n-grams?
        
        String type = typeAtt.type();
           //判断字符属性,是否是CJK字符
        if (type == doHan || type == doHiragana || type == doKatakana || type == doHangul) {
          
          // acceptable CJK type: we form n-grams from these.
          // as long as the offsets are aligned, we just add these to our current buffer.
          // otherwise, we clear the buffer and start over.
          
          if (offsetAtt.startOffset() != lastEndOffset) { // unaligned, clear queue
            if (hasBufferedUnigram()) {
              
              // we have a buffered unigram, and we peeked ahead to see if we could form
              // a bigram, but we can't, because the offsets are unaligned. capture the state 
              // of this peeked data to be revisited next time thru the loop, and dump our unigram.
              
              loneState = captureState();
              flushUnigram();
              return true;
            }
            index = 0;
            bufferLen = 0;
          }
          refill();
        } else {
          
          // not a CJK type: we just return these as-is.
          
          if (hasBufferedUnigram()) {
            
            // we have a buffered unigram, and we peeked ahead to see if we could form
            // a bigram, but we can't, because its not a CJK type. capture the state 
            // of this peeked data to be revisited next time thru the loop, and dump our unigram.
            
            loneState = captureState();
            flushUnigram();
            return true;
          }
          return true;
        }
      } else {
        
        // case 3: we have only zero or 1 codepoints buffered, 
        // so not enough to form a bigram. But, we also have no
        // more input. So if we have a buffered codepoint, emit
        // a unigram, otherwise, its end of stream.
        
        if (hasBufferedUnigram()) {
          flushUnigram(); // flush our remaining unigram
          return true;
        }
        return false;
      }
    }
  }




分享到:
评论

相关推荐

    Lucene.Net 2.3.1开发介绍 —— 二、分词(四)

    Lucene.Net 2.3.1开发介绍 —— 二、分词(四),这是一个系列的文档,太多了,只好分开

    lucene分词测试代码

    用java写的图形分词测试的小东西,用的分词器是: 来自“猎图网 www.richmap.cn”基于IKAnalyzer分词算法的准商业化Lucene中文分词器,其使用“正向全切分算法”,42万汉字字符/每秒的处理能力(IBM ThinkPad 酷睿I...

    Lucene中文分词器包

    来自“猎图网 www.richmap.cn”基于IKAnalyzer分词算法的准商业化Lucene中文分词器。 1. 正向全切分算法,42万汉字字符/每秒的处理能力(IBM ThinkPad 酷睿I 1.6G 1G内存 WinXP) 2. 对数量词、地名、路名的...

    Lucene-Demo.rar Lucene分词的demo

    本压缩包的主要内容是Lucene分词器的demo版本,可以导入到程序中直接使用,包含Lucene分词使用的pom文件,使用前请注意修改存储地址。

    Lucene中文分词器组件

    Lucene中文分词器组件,不错的。

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

    20.Lucene分词器1 共3页 21.Lucene分词器2 共9页 22.Lucene分词器3 共4页 23.Lucene项目实战1 共6页 24.Lucene项目实战2 共6页 25.Lucene项目实战3 共6页 26.Lucene项目实战4 共6页 27.Lucene项目实战5 共5页 28....

    lucene3.0 分词器

    lucene3.0 中文分词器, 庖丁解牛

    Lucene分词器资源包

    压缩包内含有Lucene分词时所需要的jar包,可以添加到本地maven当中使用,但不含demo,如需使用Lucene的demo,还请下载Lucene-Demo.rar

    lucene中文分词器(paoding解牛)

    lucene搜索引擎中文分词器,版本2.0.4,强大的中文分词效果在其它中文分词器当中独领风骚

    lucene.NET 中文分词

    lucene.NET 中文分词 高亮 lucene.NET 中文分词 高亮 lucene.NET 中文分词 高亮 lucene.NET 中文分词 高亮

    简单的LUCENE分词

    在JAVA下,用lucene的内置分词功能对XML文件进行分词,并取消无用词

    自己写的一个基于词库的lucene分词程序--ThesaurusAnalyzer

    自己写的一个基于词库的lucene分词程序--ThesaurusAnalyzer

    Jcseg支持lucene3的分词器

    在网上找了好半天也没找到jcseg分词器对lucene 3的支持,自己参考这对lucene4的支持写的,希望对大家有用。

    lucene分词包

    lucene自带的中文分词器,将jar放入编译路径即可使用

    Lucene4.0 IK分词器使用pdf

    Ik中分分词器介绍,可用于lucene4.0

    中文分词及其在基于Lucene的全文检索中的应用

    本文构造出一种适应中英文信息处理的Lucene语言分析器,该分析器的核心模块——分词器所使用的分词算法是一种基于词典的中文分词算法,该算法具体实现上采用了基于词前缀哈希技术来进行逐字匹配,采用基于规则统计...

    高版本Lucene的IK分词器

    maven库中现有的ik分词器只支持低版本的Lucene,想要支持高版本的Lucene,需要重写老版本ik分词器里的部分代码. 下载代码片段后导入项目,在创建分词器的时候把new IKAnalyzer替换为 new IKAnalyzer5x即可。

    java lucene 实现分词和词干抽取

    用java实现的,利用了lucene里面的standardAnalyzer分析器实现的分词,可以去停用词,再利用波特算法实现 词干提取 最后排序 和词频统计输出

    Lucene分词与查询详解

    Lucene分词与查询详解。这是一个完整的实例,希望对大家的开发学习有帮助!!!

    Lucene的中文分词方法设计与实现

    本文设计实现了一个中文分词模块,其主要研究目的在于寻找更为有效的中文词汇 处理方法,提高全文检索系统的中文处理能力.整个模块基于当前最流行的搜索引擎架构 Lucene,实现了带有歧义消除功能的正向最大匹配算法...

Global site tag (gtag.js) - Google Analytics