前言:msn空间丢失以及csdn空间丢失,导致很多以前写的文档都不见了~~幸好搜索到了,贴回来留念~~2007年的记忆:)
首先,我要申明,这篇文档提供的只是思路,不是解决方案,而且不针对任何分词组件。如果想看解决方案的话,请查看我的另一篇文档,《nutch0.9中使用JE分词》。
在分词的过程中,我发现其实分词包含两部分,第一部分是关于抓取结果的分词,第二部分是关于查询关键字的分词,只有当这两部分的分词一致情况下,才能查到自己想要的结果。对于结果的分词,我们可以用luke来查看是否成功,但是关键字部分的分词,只能靠各位编写输出代码来确定是否正确了。
与分词相关的文件有如下三个:
1.NutchDocumentAnalyzer.java:修改这个文件可以达到对抓取结果进行分词。我们所要做的只是需要使用自己的分词方法替换他原本的分词方法,即在返回的时候返回<my分词.tokenStream(fieldName, reader)> (该文件在:nutch\src\java\org\apache\nutch\analysis下)
2.NutchAnalysis.java:修改这个文件可以达到查询关键字的分词。通过研究发现,该文件中的查询,最终都归结到parse方法中处理,也就是说,我们更改parse方法,即能达到分词效果。 (该文件在:nutch\src\java\org\apache\nutch\analysis下)
3.Query.java:这个文件是不用修改的,之所以把它列出来是因为NutchAnalysis.java parse方法根据查询不同关键字调用Query文件中的不同add**方法,然后再由NutchAnalysis的parse方法中return出去。
关于结果分词部分实现简单,在此就不细说了。对于关键字的分词,要求就比较多了,因为我们必须保证我们修改parse能够支持nutch原本查询的一些功能,比如:
梦幻西游 有梦幻或者西游都可以
"梦幻西游" 有全部的梦幻西游四个字并且顺序一致
-"梦幻西游" 页面没有梦幻西游完整顺序四个字,原系统没有此功能,需自己实现
-梦幻西游 页面没有梦幻但是有西游两个字
梦幻-"西游" 在有梦幻的页面查询没有西游的结果
其它多重组合
为了了解nutch原本的查询机制,我做了如下测试,在没有分词的nutch中,给NutchAnalysis.java每一个方法中添加一个print语句,输出的为该方法的编号,编号从1-52,即总共52个方法。另外parse方法开头和结尾特意println出调用parse开始/调用parse结束。此后又给Query.java的8个add方法中依次加了print语句输出方法编号,编译运行,结果如下:
梦幻
4/4/41/1/6/************* parse开始 ***************
12/17/20/46/36/39/46/46/46/46/46/29/46/46/52/48/
15/18/46/52/8/9/45/16/26/24/19/46/46/35/39/46/46/46/46/46/52/12/17/20/46/36/39/46/46/46/46/46/29/46/46/52/2//query6//query2/48/
15/18/46/52/8/9/45/16/26/24/19/46/46/35/39/46/46/46/46/46/52/12/17/20/46/36/39/46/46/46/46/46/29/46/46/52/2//query6//query2/48/
************* parse结束 ***************
注:由上可见,正常查询时候调用了query6/query2方法,因为nutch原版为一元分词,因此查询了两次。
"梦幻"
4/41/1/6/************* parse开始 ***************
12/17/20/46/36/39/46/46/46/46/46/29/46/46/52/48/15/18/46/52/7/45/48/
9/45/48/9/45/48/9/45/48/9/45/48/
45/12/17/20/46/36/39/46/46/46/46/46/29/46/46/52//query6/48/
************* parse结束 ***************
注:由上可见,梦幻作为一个整体提交,调用query6。
-"梦幻"
4/41/1/6/************* parse开始 ***************
12/17/20/46/36/39/46/46/46/46/46/29/46/46/28/27/32/46/22/19/46/46/35/39/46/46/46/46/46/46/52/48/45/15/18/46/52/48/7/45/48/
9/45/48/9/45/48/9/45/48/9/45/48/
45/12/17/20/46/36/39/46/46/46/46/46/29/46/46/52//query8/48/
************* parse结束 ***************
注:由上可见,梦幻作为一个整体提交,但是调用了query8。
鉴于梦幻和"梦幻"都调用了query6方法,因此察看该方法为:
public void addRequiredPhrase(String[] terms, String field) {
if (terms.length == 0) { // ignore empty phrase
} else if (terms.length == 1) {
addRequiredTerm(terms[0], field); // optimize to term query
} else {
clauses.add(new Clause(new Phrase(terms), field, true, false, this.conf));
}
}
如上,也就是说,terms长度为1,才有可能调用addRequiredTerm(terms[0], field),而这个方法即我们所说的query2。由此证明,梦幻查询的时候,是一个词一个词直接传给query2的,而"梦幻"是多个词合成数组传进query6的,至于-"梦幻"则合成数组传给query8。另外,-梦幻则是一个一个词调用,梦调用query8,幻调用query2。
综上所述,我所推出的解决方式为:先将用户输入的关键字进行拆分,遇到正常查询的就直接分词调用query2,碰到有"的看前面又没有-号,没有就分词传数组给query6,有就分词传数组给query8,碰到有-后没有",有就分词传数组给query8,没有分词掉用query8。另外还有些没有想到的组合查询,有待各位编写代码时再作考虑了。