现在的位置: 首页 > 综合 > 正文

开源搜索框架Lucene学习之分词器(2)——TokenFilter类及其子类

2013年06月14日 ⁄ 综合 ⁄ 共 2708字 ⁄ 字号 评论关闭

      前面我们分析了一下Tokenizer类及它的子类,Tokenizer类继承于TokenStream类,它的作用主要是把一个字符串分隔成一个个的词,不同的子类实现不同的切分方式。有按空格的,有按非英文字符的。把切分出来的词Token组合成TokenStream。今天我们要讨论的是TokenFilter及其子类。TokenFilter类也是继承于TokenSteam类,它的作用是对分出来的词进行一些处理,比如去掉停词,转换大小写。我们来看TokenFilter类的代码:

abstract public class TokenFilter : TokenStream

{

    ///<summary>

    ///需要传过来的处理的TokenStream

    ///The source of tokens for this filter. 

    ///</summary>

    protected TokenStream input;

 

    ///<summary> Close the input TokenStream. </summary>

    public override void Close()

    {

        input.Close();

    }

 

}

     也是一个抽象类,它里面定义了一个受保护的成员TokenStream类型的input,我们知道在Tokenizer类里面定义了一个受保护的TextReader类型的input,Tokenizer类里面接收的是一个文本流,而TokenFilter类则需要接收一个TokenStream,也就是一个语汇单元流。具体的流程就是把一个字符串传递给Tokenizer,Tokenizer把这个字符串分拆成一个个的Token,然后把这些Token组合成一个TokenStream,也就是一个语汇单元流,然后把这个语汇单元流传给TokenFilter,TokenFilter会对TokenStream里面的每一个Token进行一下处理。根据处理方式的不同,由不同的子类来实现这些处理方式。先来看看第一个子类LowerCaseFilter,也就是把每个Token都转换成小写的。

public class LowerCaseFilter : TokenFilter

{

    /// <summary>

    /// Initializes a new instance of the LowerCaseFilter class.

    /// </summary>

    /// <param name="ts">Token stream to read from.</param>

    public LowerCaseFilter(TokenStream ts)

    {

        input = ts;

    }

 

    /// <summary>

    /// Returns the next token from the stream.

    /// </summary>

    /// <returns>The next token or null if EOS.</returns>

    public override Token Next()

    {

        Token t = input.Next();

 

        if (t == null)

            return null;

 

        t.TermText = t.TermText.ToLower();

 

        return t;

    }

}

     主要就是Next方法,里面就是把每一个Token转换成小写。方法比较简单,就不用解释了。再看第二个子类,去掉停词的类StopFilter,我们就只看Next方法,代码如下:

public override Token Next()

{

    // return the first non-stop word found

    for (Token token = input.Next(); token != null; token = input.Next())

        if (table[token.TermText] == null)

            return token;

    // reached EOS -- return null

    return null;

}

     这个方法里面有一个table变量,它是一个HashTable的对象,里面装的就是停词,也就是那些没有实际意义,需要剔除的词,这个停词集合,在这个类里面有一个初始化,也就是英文中常用的停词集合,你也可以自己传入一个停词的集合。Next方法主要就是遍历每一个Token,看其是否是停词,如果是的,就去掉。

     接下来要看的一个子类就比较有意思,它的作用就是把词元进行一些Stem处理,Stem就是把每一个词元还原成原型,比如cars转换成car。这里会用到一个著名的的stemming算法,全称是The Porter Stemming Algorithm,其主页为http://tartarus.org/~martin/PorterStemmer/,也可查看其论文http://tartarus.org/~martin/PorterStemmer/def.txt。通过以下网页可以进行简单的测试:Porter's Stemming Algorithm Online[http://facweb.cs.depaul.edu/mobasher/classes/csc575/porter.html]。比如cars –> car,driving –> drive,tokenization –> token。下面我们来看看这个类的Next方法:

public override Token Next()

{

    Token token = input.Next();

    if (token == null)

        return null;

    else

    {

        String s = stemmer.stem(token.TermText);

        if (s != token.TermText) // Yes, I mean object reference comparison here

            token.TermText = s;

        return token;

    }

}

    当然首先是定义了一个封装了stemming算法的类PorterStemmer的对象stemmer,然后调用这个里面的stem方法,把每一个Token都处理一下,返回即可。有时间的话把stemming算法单独拿出来解读一下。

    分词的一些基本类都已经介绍完成了,前面所介绍的都是一些简单的分词,Lucene里面内置了四个分词器,分别是WhitespaceAnalyzer,SimpleAnalyzer,StopAnalyzer还有一个StandardAnalyzer分词器,前三个分词器用前面介绍的一些类就可以完成其功能,StandardAnalyzer分词器比较复杂,下次将来解读,构成StandardAnalyzer分词器的StandardFilter类和StandardTokenizer类。

抱歉!评论已关闭.