Mysoo2 站内搜索引擎安装指南
百度阿拉丁平台剑指垂直搜索
谷歌测试在搜索建议中放广告
谷歌与百度的八年“暗战”
Google公布2008年度搜索排行榜
传戴尔PC将放弃谷歌选择微软Live搜索引擎
雅虎高级搜索专家陆奇将任微软数字部门高管
微软不娶雅虎 只想买搜索业务
微软退出搜索市场能对Google造更大伤害
雅虎打造BOSS垂直搜索引擎
谷歌百度口水战升级 比拼"谁更懂中文"
从百度“竞价门”看企业的社会责任感
山寨版搜索引擎“百谷虎”雷倒网友
雅虎搜索技术高管跳槽至微软
面对“搜索门” 百度公司力挽声誉
内容更新频率对SEO的影响


 ·数学之美系列三:隐含马尔可夫模型
 ·数学之美系列二:谈谈中文分词
 ·数学之美系列一:统计语言模型
 ·如何使用Lucene进行全文检索(三)
 ·如何使用Lucene进行全文检索(二)





实现NUTCH中文分词的代码修改方法


 共1页 

  此处我修改的nutch版本是0.7.2

  现在实现基本中文分词功能的代码和软件模块很多,性能也还可以,但是怎样将其应用到NUTCH中的方法介绍相对较少,下面我就实现NUTCH中文分词的NUTCH代码修改方法与步骤,抛砖引玉的介绍一下。

  代码修改的切入点是通过对NUTCH处理中文的切分器Tokenizer的修改或者替换(这里介绍的是替换),使中文分词由单字切分变为词语切分。对于相关的NUTCH基本知识,我就不赘述了。因为NUTCH的检索功能基于Lucene,所以你用来替换的切分器必须满足Lucene的Tokenizer特征,最主要的是保证输入与输出相符,分词后输出的必须是Token流。幸运的是,现存的分词程序或软件模块基本上都满足此需要,即使有所偏差,一般通过对其输入输出的修改就可以满足需要。我前面提供给大家的那个分词程序就可以经过简单修改应用于NUTCH中。

  设我们实现中文分词功能模块的主类名为MYTokenizer,package为org.apache.nutch.analysis.myt. MYTokenizer,将模块假如项目后,NUTCH代码修改如下:

  (需要修改或新增的行后有注释,否则其它行只是为了定位,不修改)

  一、修改org\apache\nutch\analysis下的NutchAnalysis.jj文件(此文件由JACC生成)

  文件第33行附近:

  import org.apache.nutch.searcher.Query.Clause; 

  import org.apache.lucene.analysis.StopFilter; 

  +import org.apache. nutch.analysis. myt. MYTokenizer; //新增此行,加入你的切分器

  import java.io.*; 

  import java.util.*;

  文件第8 1行附近:

  PARSER_END(NutchAnalysis) 

  TOKEN_MGR_DECLS : {

  /** use MYTokenizer to process cjk character */ //新增此行注释

  private MYTokenizer myTokenizer = null;   //新增此行

  /** a global cjk token */   //新增此行注释

  private org.apache.lucene.analysis.Token cjkToken = null;     //新增此行,输出流

  /** start offset of cjk sequence */   //新增此行注释

  private int cjkStartOffset = 0;   //新增此行

  /** Constructs a token manager for the provided Reader. */

  public NutchAnalysisTokenManager(Reader reader) {

  文件第106行附近:

  }

  // chinese, japanese and korean characters 

  | <SIGRAM: <CJK> >   //删除此行

  | <SIGRAM: (<CJK>)+ >   //新增此行(#行)

  //以下所有行均为新增,紧接上行代码(#行)书写

  { 

  /** 

  * use an instance of myTokenizer, myTokenizer, hold the maximum 

  * matched cjk chars, and cjkToken for the current token; 

  * reset matchedToken.image use cjkToken.termText();

  * reset matchedToken.beginColumn use cjkToken.startOffset();

  * reset matchedToken.endColumn use cjkToken.endOffset();

  * backup the last char when the next cjkToken is valid. 

  */ 

  if(myTokenizer == null) { 

  myTokenizer = new MYTokenizer (new StringReader(image.toString()));

  cjkStartOffset = matchedToken.beginColumn; 

  try { 

  cjkToken = myTokenizer.next();

  } catch(IOException ioe) { 

  cjkToken = null; 

  } 

  } 

  if(cjkToken != null && !cjkToken.termText().equals("")) { 

  //sometime the myTokenizer returns an empty string, is it a bug? 

  matchedToken.image = cjkToken.termText();

  matchedToken.beginColumn = cjkStartOffset + cjkToken.startOffset();

  matchedToken.endColumn = cjkStartOffset + cjkToken.endOffset();

  try { 

  cjkToken = myTokenizer.next();

  } catch(IOException ioe) { 

  cjkToken = null; 

  } 

  if(cjkToken != null && !cjkToken.termText().equals("")) { 

  input_stream.backup(1); 

  } 

  } 

  if(cjkToken == null || cjkToken.termText().equals("")) {

  myTokenizer = null; 

  cjkStartOffset = 0; 

  }

  }

  二、修改org\apache\nutch\searcher下的Summarizer.java文件(此处修改为提高搜索性能)

  文件第189行附近:

  将原代码段

  if (highlight.contains(t.termText())) {

  excerpt.addToken(t.termText());

  excerpt.add(new Fragment(text.substring(offset, t.startOffset())));

  excerpt.add(new Highlight(text.substring(t.startOffset(),t.endOffset())));

  offset = t.endOffset();

  endToken = Math.min(j+SUM_CONTEXT, tokens.length);

  }

  修改为:

  if (highlight.contains(t.termText())) {

  if(offset * 2 == (t.startOffset() + t.endOffset() )) { // cjk bi-gram

  excerpt.addToken(t.termText().substring(offset - t.startOffset()));

  excerpt.add(new Fragment(text.substring(t.startOffset() + 1,offset)));

  excerpt.add(new Highlight(text.substring(t.startOffset() + 1 ,t.endOffset())));

  } 

  else { 

  excerpt.addToken(t.termText());

  excerpt.add(new Fragment(text.substring(offset, t.startOffset())));

  excerpt.add(new Highlight(text.substring(t.startOffset() ,t.endOffset())));

  }

  offset = t.endOffset();

  endToken = Math.min(j+SUM_CONTEXT, tokens.length);

  }   

  为了提高运行效率,你的分词模块在运行中最好可以将词表读入内存。至于代码修改的原理,说来话长,容后再叙。

 共1页 

来源: blog.donews.com/52se | 作者: | 发表时间: 2007-1-18 11:00:00

 

 


Copyright © 2000-2008 Mysoo.com.cn, All Rights Reserved Mysoo.com.cn 版权所有                                  把Mysoo添加到 Google   沪ICP备06051139