关于Lucene.net中文分词后的结果着色问题
2010-03-12 13:52
363 查看
近日工作中有一个项目使用到了Lucene.net,在工作中发现了一个问题,就是如果采用Lucene自带的分词器是对关键字按字来进行拆分的,这样搜索到的结果肯定不符合我们的要求。后来在网上找了一个中文分词工具,就是车东老师写的CJK分词器,可当采用CJK二元分词法以后,却发现一个问题,搜索到的结果是对的,但着色是错误的,比如我们对如下文本进行搜索
我是一个中国人,我是一个伟大的中国人
当采用关键字伟大进行搜索的时候
会着色成这样
我是一个中国人,<span class=/"keyword/">我是一个伟大的中国人</span>
而我们需要的当然是
我是一个中国人,我是一个<span class=/"keyword/">伟大</span>的中国人
刚开始还以为是Lucene.net不支持中文着色的问题,后来在Lucene.net的开源网站上下载了一个3.0的版本,跟踪进去后,发现仍然没有解决这个问题,这个问题的原因出在Highlighter.Net_Source这个类库中的TokenGroup类有一个IsDistinct方法,这个方法只有一句代码 return (token.StartOffset() >= this.endOffset); 由于英文是通过空格来区分每个词的,所以token.StartOffset()是会出现大于等于his.endOffset的情况的,但中文是不通过空格来分隔的,这样就只有再Lucene遇到,。;等分隔符的时候,它才会判断为一段词结束,原因找到了以后,就开始想一下解决办法了,没有想的什么太好的办法,最后采用的是中文虽然没有分隔符,但不妨碍我们自己增加分隔符号,可以找到每个关键字的索引,然后再对应关键字头尾增加分隔符,这样就解决了这个问题,当然最好的办法还是直接重写Highlighter类库,加入对中文日文韩文这种文字型语言的支持,这点希望有加入这个开源项目的朋友反馈一下
附带源代码如下
我是一个中国人,我是一个伟大的中国人
当采用关键字伟大进行搜索的时候
会着色成这样
我是一个中国人,<span class=/"keyword/">我是一个伟大的中国人</span>
而我们需要的当然是
我是一个中国人,我是一个<span class=/"keyword/">伟大</span>的中国人
刚开始还以为是Lucene.net不支持中文着色的问题,后来在Lucene.net的开源网站上下载了一个3.0的版本,跟踪进去后,发现仍然没有解决这个问题,这个问题的原因出在Highlighter.Net_Source这个类库中的TokenGroup类有一个IsDistinct方法,这个方法只有一句代码 return (token.StartOffset() >= this.endOffset); 由于英文是通过空格来区分每个词的,所以token.StartOffset()是会出现大于等于his.endOffset的情况的,但中文是不通过空格来分隔的,这样就只有再Lucene遇到,。;等分隔符的时候,它才会判断为一段词结束,原因找到了以后,就开始想一下解决办法了,没有想的什么太好的办法,最后采用的是中文虽然没有分隔符,但不妨碍我们自己增加分隔符号,可以找到每个关键字的索引,然后再对应关键字头尾增加分隔符,这样就解决了这个问题,当然最好的办法还是直接重写Highlighter类库,加入对中文日文韩文这种文字型语言的支持,这点希望有加入这个开源项目的朋友反馈一下
附带源代码如下
/// <summary> /// 对关键字所在索引比较 /// </summary> /// <param name="str1">关键字索引1</param> /// <param name="str2">关键字索引2</param> /// <returns>相等返回0,关键字索引1大则返回1,否则返回-1</returns> private int CompareStrIndex(string str1, string str2) { if (string.IsNullOrEmpty(str1)) { if (string.IsNullOrEmpty(str2)) { return 0; } else { return -1; } } else { if (string.IsNullOrEmpty(str2)) { return 1; } else { int x; int y; string[] str1Arr = str1.Split(','); string[] str2Arr = str2.Split(','); int.TryParse(str1Arr[0], out x); int.TryParse(str2Arr[0], out y); return x.CompareTo(y); } } } /// <summary> /// 给文本增加分隔符 /// </summary> /// <param name="text">需要处理文本</param> /// <param name="KeyWords">关键字</param> /// <returns>处理后的文本</returns> public string AddSeparator(string text,string KeyWords) { if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(KeyWords)) { return string.Empty; } if (text.Length <= 2) { return text; } string Result = string.Empty; KeyWords = KeyWords.Replace(" "," "); string[] KeyWordArr = KeyWords.Split(new char[1] { ' ' }); List<string> KeyWordList = new List<string>(); //构建2元分隔关键字列表 Char OldChar = char.MinValue; foreach (string KeyWord in KeyWordArr) { foreach (char Chr in KeyWord) { if (OldChar == char.MinValue) { OldChar = Chr; } else { KeyWordList.Add(OldChar.ToString() + Chr.ToString()); OldChar = Chr; } } OldChar = char.MinValue; } //获取关键字在文本中出现的索引并排序 List<string> StartIndexList = new List<string>(); List<string> StartIndexListResult = new List<string>(); foreach (string KeyWord in KeyWordList) { MatchCollection Matches = Regex.Matches(text, KeyWord, RegexOptions.Compiled | RegexOptions.IgnoreCase); foreach (Match NextMatch in Matches) { StartIndexList.Add(NextMatch.Index + "," + (NextMatch.Index + 1)); } } StartIndexList.Sort(CompareStrIndex); //合并重复出现的文本部分 string OldIndex = string.Empty; foreach (string StrIndex in StartIndexList) { if (OldIndex == string.Empty) { OldIndex = StrIndex; } else { string[] OldIndexArr = OldIndex.Split(','); string[] IndexArr = StrIndex.Split(','); if (int.Parse(IndexArr[0]) - int.Parse(OldIndexArr[1]) <= 1) { OldIndex = OldIndexArr[0] + "," + IndexArr[1]; } else { StartIndexListResult.Add(OldIndex); OldIndex = StrIndex; } } } if (OldIndex.Length > 0) { StartIndexListResult.Add(OldIndex); } //插入分隔符 int Increment = 0; Result = text; char Separator = Char.MaxValue; foreach (string ResultIndex in StartIndexListResult) { string[] ResultIndexArr = ResultIndex.Split(','); Result = Result.Insert(int.Parse(ResultIndexArr[0]) + Increment++, Separator.ToString()); Result = Result.Insert(int.Parse(ResultIndexArr[1]) + 1 + Increment++, Separator.ToString()); } return Result; }
相关文章推荐
- lucene.net 2.0 中文分词后语法高亮问题
- lucene.net 2.0 中文分词后语法高亮问题
- Lucene.net 2.0 中文分词后语法高亮问题
- [转]lucene.net 2.0 中文分词后语法高亮问题
- 基于Syntaxnet的中文分词问题
- php、asp.net关于后台设置的cookie前台JS获取时出现中文乱码问题解决
- Lucene4:获取中文分词结果,根据文本计算boost
- 解决ASP.NET MD5加密中文结果和ASP不一致的问题
- 【分享】Lucene.Net的中文分词组件AdvancedChineseAnalyzer
- 关于asp.net页面通过url传值,中文出现乱码的一些有趣的问题~~~
- 关于windows7下asp.net生成pdf中文显示问题
- Lucene.net中文分词探究
- 关于asp.net中文文件名超长的下载问题
- 【分享】Lucene.Net的中文分词组件AdvancedChineseAnalyzer
- Lucene.net(4.8.0)+PanGu分词器 问题记录一 分词器Analyzer的构造和内部成员ReuseStategy
- 关于ubuntu10.04触摸板不能禁用和gedit文本编辑器中文乱码问题的一个解方案 转自:http://blog.csdn.net/luodayuan/archive/2010/05/23/5617615.aspx
- Lucene.net 搜索引擎中中文词组分词的实现
- Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考
- ASP.NET关于前台脚本传递中文参数,后台获取乱码问题(乱码为方框,黑色方框等。。)
- Javascript与ASP.NET(一般处理程序)关于URL(get方式)传递中文乱码问题的解决方案