在DotLucene/Lucene.net中, 增加自己的中文分词Analyzer

研究了一天终于搞定了在Lucene.net 里添加Analyzer 的方法。首先说明下,要添加中文分词必须继承Analyzer类。

参考网址:http://blog.likeshow.net/article.asp?id=39

仿照别人的一篇文章,写出了这个类。写完后发现,其实这样的东西没什么技术含量,不过对于理解Lucene确实帮助不少。下面我将代码贴出。

首先是:ChineseAnalyzer 类,这个类里面从别人的类中已经有现成的了。上面网址所说的方法有点不对,到了2.0里面,ChineseTokenizer 应该继承 Tokenizer 类,而Tokenizer类的构造函数只能传 TextReader _in 。所以 ChineseAnalyzer 类就保持原有的不变。

代码如下:

public class ChineseAnalyzer : Analyzer
{

   public ChineseAnalyzer()
   {
   }

   /// <summary>
   /// Creates a TokenStream which tokenizes all the text in the provided Reader.
   /// </summary>
   /// <returns>A TokenStream build from a ChineseTokenizer filtered with ChineseFilter.</returns>
   public override sealed TokenStream TokenStream(String fieldName, TextReader reader)
   {
    TokenStream result = new ChineseTokenizer(reader);  
    result = new ChineseFilter(result);
    return result;
   }
}

从上面可以看出,一个 Analyzer 类必须有 2个类与之对应: ChineseTokenizer , ChineseFilter 。前面一个类是我们需要修改的,也就是用中文分词技术将读进去的 TextReader 变成 一个个的 Token 。 既然不能传2个参数,那么中文分词只能在 ChineseTokenizer 里出现了。

此类代码如下:

public sealed class ChineseTokenizer : Tokenizer
{

   private Segment segment; //分词类。
   private string[] Wordlist; //切好的词放入此数组中
   private string Allstr; //对传入的流转成此string
   private int offset = 0; int start = 0; int step = 0; //offset偏移量,start开始位置,step次数

   public ChineseTokenizer(TextReader _in)
   {
    input = _in;
    Allstr = input.ReadToEnd(); //把流读到Allstr
    segment=new Segment();
    segment.InitWordDics();
    segment.Separator="|";
    Wordlist = segment.SegmentText(Allstr).Split('|'); //把分好的词装入wordlist
   }

  
   private Token Flush(string str)
   {

    if (str.Length > 0)
    {
     return new Token(str,start, start + str.Length); //返回一个Token 包含词,词在流中的开始位置和结束位置.
    }
    else
     return null;
   }

   public override Token Next() //重载Next函数,就是返回Token
   {
    Token token = null;
    if (step < Wordlist.Length)
    {
     start = Allstr.IndexOf(Wordlist[step], offset); //从Allstr里找每个分出来词汇的开始位置
     offset = start + 1; //计算偏移量
     token = Flush(Wordlist[step]); //返回已分词汇
     step = step + 1; //变量+1,移动到wordlist的下一个词汇
    }
    return token;
   }

}

而最后一个类,基本不用改变。

public sealed class ChineseFilter : TokenFilter
{
   // Only English now, Chinese to be added later.
   public static String[] STOP_WORDS =
     {
      "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"
     };

   private Hashtable stopTable;

   public ChineseFilter(TokenStream _in) : base (_in)
   {
    stopTable = new Hashtable(STOP_WORDS.Length);

    for (int i = 0; i < STOP_WORDS.Length; i++)
     stopTable[STOP_WORDS[i]] = STOP_WORDS[i];
   }

   public override Token Next()
   {

    for (Token token = input.Next(); token != null; token = input.Next())
    {
     String text = token.TermText();

     // why not key off token type here assuming ChineseTokenizer comes first?
     if (stopTable[text] == null)
     {
      switch (Char.GetUnicodeCategory(text[0]))
      {

       case UnicodeCategory.LowercaseLetter:
       case UnicodeCategory.UppercaseLetter:

        // English word/token should larger than 1 character.
        if (text.Length > 1)
        {
         return token;
        }
        break;
       case UnicodeCategory.OtherLetter:

        // One Chinese character as one Chinese word.
        // Chinese word extraction to be added later here.

        return token;
      }

     }

    }
    return null;
   }
}

至此中文分词就完全搞定了。用java版的Luke 可以看到里面出现了中文的分词。又一次证明了Lucene.net 和 Lucene的索引是通用的。

在这里要利用了开源的 分词库: http://www.shootsoft.net/home/show.aspx?id=38&cid=8 感谢作者无私分享,在网上找了好多天,才找到这个开源的分词程序,而且带有分词字典。

至此,终于完成了一个简单的中文全文检索程序了。明天开始测试这个程序的性能。并且换几个其他的分词程序试试看效果。后天利用这个做一个简单的全文检索程序,将我一个5万编程文档的网站实现全文检索。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值