Nutch中文分词(庖丁解牛)_庖丁解牛分词器整合es-程序员宅基地

技术标签: 扩展  java  stream  ant  lucene  token  

1 中文分词介绍 
中文分词是在做检索类系统时需要重点考虑的一个因素。Nutch的本土化过程也需要更改对中文分词的支持。目前,Nutch中文分词方式大致有两种方式:
一是修改源代码。这种方式是直接对Nutch分词处理类进行修改,调用已写好的一些分词组件进行分词。
二是编写分词插件。这种方式是按照Nutch定义的插件编写规则重新编写或者添加中文分词插件。
以上两种方式都是可取的。目前,由于开源社区的活跃,已经有很多种分词组件的出现,无论是修改源代码的方式还是编写分词插件的方式,都是依赖于这些分词组件的。下面列出了主要的一些分词组件:
1、CJKAnalyzer
Lucene自带的一种中日韩分词器。
2、ChineseAnalyzer 
Lucene自带的对中文的分词器
3、IK_CAnalyzer(MIK_CAnalyzer)
一种基于词典的分词器,Lucene自带,相对而言较简单。
4、Paoding分词
比较有名的庖丁解牛分词组件,效率高分词速度快,分词准确度高。
5、JE分词
网友编写的分词组件,性能也不错。
6、ICTCLAS
中科院的一组分词工具,其中有开源的也有收费版本,他基于HMM模型。主要的几个如下:
ICTCLAS_OpenSrc_C_windows、ICTCLAS_OpenSrc_C_Linux为中科院计算所张华平和刘群老师研制。
SharpICTCLAS为.net平台下的ICTCLAS,是由河北理工大学经管学院吕震宇根据Free版ICTCLAS改编而成,并对原有代码做了部分重写与调整。 
ictclas4j中文分词系统是sinboy在中科院张华平和刘群老师的研制的FreeICTCLAS的基础上完成的一个java开源分词项目,简化了原分词程序的复杂度,旨在为广大的中文分词爱好者一个更好的学习机会。
imdict-chinese-analyzer是 imdict智能词典的智能中文分词模块,作者高,算法基于隐马尔科夫模型(Hidden Markov Model, HMM),是中国科学院计算技术研究所的ictclas中文分词程序的重新实现(基于Java),可以直接为lucene搜索引擎提供中文分词支持。
2 分词结构分析 

在进行实验之前需要对Nutch分词结构进行分析。本文仔细研究了一下Nutch的org.apache.nutch.anlysis包,其中大多的类都 是与Nutch在爬行网页时候对网页中的文本分词解析相关的。Nutch解析文本类的架构得非常好,下面就让我们来研究下它的架构吧,了解清楚之后就可以 为我们之后加入中文分词打下很好的基础。
    Nutch分词的最底层使用的是lucene的Analyzer抽象类,它位于org.apache.lucene.analysis包 中,NutchAnalyzer继承了Analyzer类、实现了Configurable、Pluggable接口,该抽象类中定义了一个公有的抽象方 法tokenStream(String fieldName, Reader reader)返回的类型是TokenStream。该方法是用于分析文本,其后的具体类中在这个方法中实现了从文本中提取索引词组的策略、算法。而返回 的TokenStream类是即可以从文本或者从查询词组中枚举token序列的抽象类,在Lucene中继承了它的具体类有Tokenizer、 TokenFilter。
    NutchAnalyzer类是Nutch中扩展分析文本的扩展点,所有用于解析文本的插件都得实现这个扩展点。对于Analyzer一个典型的扩展就是 首先建立一个Tokenizer(org.apache.lucene.analysis.Tokenizer),它是用于将Reader中读入的 Stream分解成最原始的词组(Token---org.apache.lucene.analysis.Token),在Tokenzier分解 Stream之后,一个或多个TokenFilter会用于过滤这些词组中无意义的词组。
NutchDocumentAnalyzer类继承了NutchAnalyzer,其中有三个静态私有内部类ContentAnalyzer、 AnchorFilter、AnchorAnalyzer 它们分别继承了Analyzer(org.apache.lucene.analysis.Analyzer)、 TokenFilter(org.apache.lucene.analysis.TokenFilter)、 Analyzer(org.apache.lucene.analysis.Analyzer)。在ContentAnalyzer中调用了 CommonGrams类(org.apache.nutch.analysis),该类构建了一个n-grams的分词方案,因为需要在索引中考虑词组 的出现频率,并且实现了对n-grams方案词组查询的优化措施。在n-grams方案中单个的词组同样会被该方案索引,索引期间大量使用了 Token(org.apache.lucene.analysis.Token)的各种方法,并且还会调用nutch/conf/nutch- default.xml中analysis.common.terms.file的配置属性。
    其上各个类与接口的uml图如下:


    对应前面一篇文章就可以再仔细研究Nutch其他结构就可以大概知道如何在Nutch中加入中文的分词方法了,从分析中我们可以看出来,Nutch的分词 大量使用了Lucene的基本抽象类或接口,这也是与两个项目的主持人同为Doug Cutting分不开的,当然了Lucene的良好架构也奠定了各种应用对其扩展使用的基础。

3 实验过程 
本次实验选择了paoding分词组件和imdict-chinese-analyzer作为实验工具。
3.1 paoding plugin 

以下是paoding分词组件的实验:
1、实验准备
下载paoding分词组件(下载地址:http://code.google.com/p/paoding/ )将下载下的文件paoding-analysis-2.0.4-beta.zip解压,得到paoding-analysis.jar。
本次实验假设Nutch已配置好。
2、在src/plugin下面新建一个目录:analysis-zh作为分词组件包,新建一个lib-paoding-analyzers存放paoding-analysis.jar。
3、在analysis-zh包中建立两个文件一个文件夹,分别为:

Java代码    收藏代码
  1. <span style="font-size: small;">build.xml:  
  2. <project name="analysis-zh" default="jar-core">  
  3. <import file="../build-plugin.xml"/>  
  4. <!-- Build compilation dependencies -->  
  5. <target name="deps-jar">  
  6.     <ant target="jar" inheritall="false" dir="../lib-paoding-analyzers"/>  
  7. </target>  
  8. <!-- Add compilation dependencies to classpath -->  
  9. <path id="plugin.deps">  
  10.     <fileset dir="${nutch.root}/build">  
  11.       <include name="**/lib-paoding-analyzers/*.jar" />  
  12.     </fileset>  
  13. </path>  
  14. </project>  
  15.   
  16. plugin.xml:  
  17. <plugin  
  18.    id="analysis-zh"  
  19.    name="Paoding Analysis Plug-in"  
  20.    provider-name="net.paoding">  
  21.    <runtime>  
  22.       <library name="paoding-analysis.jar">  
  23.          <export name="*"/>  
  24.       </library>  
  25.    </runtime>  
  26.    <requires>  
  27.       <import plugin="nutch-extensionpoints"/>  
  28.       <import plugin="lib-lucene-analyzers"/>  
  29.    </requires>  
  30.    <extension id="org.apache.nutch.analysis.zh"  
  31.               name="Paoding Analyzer"  
  32.               point="org.apache.nutch.analysis.NutchAnalyzer">  
  33.       <implementation id="PaodingAnalyzer"  
  34.                       class="org.apache.nutch.analysis.zh.PaodingAnalyzer">  
  35.         <parameter name="lang" value="fr"/>  
  36.       </implementation>  
  37.    </extension>  
  38. </plugin>  
  39.   
  40. Src/Java文件夹,里面新建一个包:org/apache/nutch/analysis/zh,在该包内新建文件PaodingAnalyzer.java:  
  41. package org.apache.nutch.analysis.zh;  
  42.   
  43. import java.io.Reader;  
  44.   
  45. import org.apache.lucene.analysis.Analyzer;  
  46. import org.apache.lucene.analysis.TokenStream;  
  47.   
  48. public class PaodingAnalyzer {  
  49.   
  50.     private final static Analyzer ANALYZER =  
  51.             new net.paoding.analysis.analyzer.PaodingAnalyzer();  
  52.     
  53.     /** Creates a new instance of ChineseAnalyzer */  
  54.     public PaodingAnalyzer() { }  
  55.   
  56.     public TokenStream tokenStream(String fieldName, Reader reader) {  
  57.         return ANALYZER.tokenStream(fieldName, reader);  
  58.     }  
  59. }  
  60.   
  61. 在lib-paoding-analyzers文件夹下建立如下文件:  
  62. build.xml:  
  63. <?xml version="1.0"?>  
  64. <project name="lib-paoding-analyzers" default="jar">  
  65. <import file="../build-plugin.xml"/>  
  66. <!--  
  67.    ! Override the compile and jar targets,  
  68.    ! since there is nothing to compile here.  
  69.    ! -->  
  70. <target name="compile" depends="init"/>  
  71.   
  72. <target name="jar" depends="compile">  
  73.     <copy todir="${build.dir}" verbose="true">  
  74.       <fileset dir="./lib" includes="**/*.jar"/>  
  75.     </copy>  
  76. </target>  
  77.   
  78. </project>  
  79.   
  80. plugin.xml:  
  81. <?xml version="1.0" encoding="UTF-8"?>  
  82. <plugin  
  83.    id="lib-paoding-analyzers"  
  84.    name="Paoding Analysers"  
  85.    provider-name="net.paoding">  
  86.    <runtime>  
  87.      <library name="lib-paoding-analyzers.jar">  
  88.         <export name="*"/>  
  89.      </library>  
  90.    </runtime>  
  91. </plugin></span>  

 


新建一个lib文件夹,将paoding-analysis.jar放入其中。

另外,修改NutchDocumentAnalyzer为:


Java代码    收藏代码
  1. <span style="font-size: small;">package org.apache.nutch.analysis;  
  2.   
  3. // JDK imports  
  4. import java.io.Reader;  
  5. import java.io.IOException;  
  6.   
  7. // Lucene imports  
  8. import org.apache.lucene.analysis.Analyzer;  
  9. import org.apache.lucene.analysis.TokenFilter;  
  10. import org.apache.lucene.analysis.TokenStream;  
  11. import org.apache.lucene.analysis.Token;  
  12. import org.apache.hadoop.conf.Configuration;  
  13. import net.paoding.analysis.analyzer.PaodingAnalyzer;  
  14.   
  15. /** 
  16. * The analyzer used for Nutch documents. Uses the JavaCC-defined lexical 
  17. * analyzer {@link NutchDocumentTokenizer}, with no stop list. This keeps it 
  18. * consistent with query parsing. 
  19. */  
  20. public class NutchDocumentAnalyzer extends NutchAnalyzer {  
  21.   
  22. //加入庖丁解牛分词器属性  
  23. private static Analyzer PAODING_ANALYZER;  
  24.   
  25. /** Analyzer used to index textual content. */  
  26. private static Analyzer CONTENT_ANALYZER;  
  27. // Anchor Analysis  
  28. // Like content analysis, but leave gap between anchors to inhibit  
  29. // cross-anchor phrase matching.  
  30. /** 
  31.    * The number of unused term positions between anchors in the anchor field. 
  32.    */  
  33. public static final int INTER_ANCHOR_GAP = 4;  
  34. /** Analyzer used to analyze anchors. */  
  35. private static Analyzer ANCHOR_ANALYZER;  
  36.   
  37. /** 
  38.    * @param conf 
  39.    */  
  40. public NutchDocumentAnalyzer(Configuration conf) {  
  41.     this.conf = conf;  
  42.     CONTENT_ANALYZER = new ContentAnalyzer(conf);  
  43.     ANCHOR_ANALYZER = new AnchorAnalyzer();  
  44.     PAODING_ANALYZER = new PaodingAnalyzer();  
  45. }  
  46.   
  47. /** Analyzer used to index textual content. */  
  48. private static class ContentAnalyzer extends Analyzer {  
  49.     private CommonGrams commonGrams;  
  50.   
  51.     public ContentAnalyzer(Configuration conf) {  
  52.       this.commonGrams = new CommonGrams(conf);  
  53.     }  
  54.   
  55.     /** Constructs a {@link NutchDocumentTokenizer}. */  
  56.     public TokenStream tokenStream(String field, Reader reader) {  
  57.       return this.commonGrams.getFilter(new NutchDocumentTokenizer(reader),  
  58.           field);  
  59.     }  
  60. }  
  61.   
  62. private static class AnchorFilter extends TokenFilter {  
  63.     private boolean first = true;  
  64.   
  65.     public AnchorFilter(TokenStream input) {  
  66.       super(input);  
  67.     }  
  68.   
  69.     public final Token next() throws IOException {  
  70.       Token result = input.next();  
  71.       if (result == null)  
  72.         return result;  
  73.       if (first) {  
  74.         result.setPositionIncrement(INTER_ANCHOR_GAP);  
  75.         first = false;  
  76.       }  
  77.       return result;  
  78.     }  
  79. }  
  80.   
  81. private static class AnchorAnalyzer extends Analyzer {  
  82.     public final TokenStream tokenStream(String fieldName, Reader reader) {  
  83.       return new AnchorFilter(CONTENT_ANALYZER.tokenStream(fieldName, reader));  
  84.     }  
  85. }  
  86.   
  87. /** Returns a new token stream for text from the named field. */  
  88. public TokenStream tokenStream(String fieldName, Reader reader) {  
  89.     Analyzer analyzer;  
  90.     /* 
  91.     if ("anchor".equals(fieldName)) 
  92.       analyzer = ANCHOR_ANALYZER; 
  93.     else 
  94.       analyzer = CONTENT_ANALYZER; 
  95. */  
  96.     analyzer = PAODING_ANALYZER;  
  97.     return analyzer.tokenStream(fieldName, reader);  
  98. }  
  99. }</span>  

 

4 编辑src/plugin下面的build.xml新增入如下内容:

Java代码    收藏代码
  1. <span style="font-size: small;"><ant dir="analysis-zh" target="deploy"/><!--maojin 20090503 add-->  
  2. <ant dir="lib-paoding-analyzers" target="deploy"/><!--maojin 20090503 add-->  
  3.   
  4. 。。。。。。  
  5. <ant dir="analysis-zh" target="clean"/><!--maojin 20090503 add-->  
  6. <ant dir="lib-paoding-analyzers" target="clean"/><!--maojin 20090503 add--></span>  

 

 

5 下载配置ant运行ant,需要进入nutch目录:
D:\nutch>D:\program\ant\bin\ant

6 将paoding-analysis.jar加入到系统的classpath中。测试:

Java代码    收藏代码
  1. <span style="font-size: small;">$ bin/nutch index plainindex/paodingindexes plainindex/crawldb plainindex/linkdb plainindex/segments/20090528132511 plainindex/segments/20090528132525 plainindex/segments/20090528132602  
  2. Indexer: starting  
  3. Indexer: done  
  4.   
  5. bin/nutch index plainindex2/paodingindexes plainindex2/crawldb plainindex2/linkdb plainindex2/segments/20090528132918 plainindex2/segments/20090528132934 plainindex2/segments/20090528133008  
  6. 合并:  
  7. $ bin/nutch merge plainindex/paodingindex plainindex/paodingindexes  
  8. merging indexes to: plainindex/paodingindex  
  9. Adding file:/d:/nutch/plainindex/paodingindexes/part-00000  
  10. done merging  
  11. 去重:  
  12. Administrator@d6369c401d1240d /cygdrive/d/nutch  
  13. $ bin/nutch dedup plainindex/paodingindex  
  14. Dedup: starting  
  15. Dedup: adding indexes in: plainindex/paodingindex  
  16. Dedup: done</span>  

 

 

试着去索引:

用luke查看:

7 修改索引名称,将原来的index和indexes分别改为index_old和indexes_old,将paodingindexes和paodingindex改为indexes和index。
8 修改查询NutchAnalysis.jj将这一行改为:| <SIGRAM: (<CJK>)+ >,用JAVACC重新编译后替换相应文件,若有错误更改(实验时报的错误是ParseException没有throw)。
9 用ant重新编译。
10将nutch-0.x.x.job文件拷贝出来替换nutch目录下的同名文件。
将\build\classes\org\apache\nutch\analysis目录下的所有文件拷贝替换nutch-0.x.x.jar中org\apache\nutch\analysis目录下的文件。
11将nutch-0.x.x.jar文件和你的分词包(我的是analysis-zh.jar)拷贝到tomcat中WEB-INF\lib下面。
12 查询。
3.2 imdict-chinese-analyzer 

中科院的ICTCLAS(Institute of Computing Technology, Chinese Lexical Analysis Syst em)是在层叠隐马尔可夫模型(Cascaded Hidden Markov Model,CHMM)上发展起来的。它的一个特色是几乎把汉语词法分析的所有环节都统一到了一个完整的理论框架中,获得很好的总体效果,而且它在分词精 度与分析速度这两个相互制约的因素上达到了一个较好的平衡,它已成为目前最好的汉语词法的分析器。具体使用版本为高编写的imdict- chinese-analyzer,它是imdict智能词典的智能中文分词模块,能直接为Lucene和Nutch使用。基于它二次开发相对灵活,因此 本文采用在该组件的基础上对原代码直接进行修改来实现,同时本文加入了停止词处理功能。
进行中文分词二次开发关键步骤为:
第一,将imdict-chinese-analyzer生成jar包,并导入到Nutch的class-pa th中。
第二,修改NutchDocumentAnalyzer的tokenStream方法体为:
Set<String> stopWords = ChineseAnalyzer.loadStopWords(AnalyzerProfile.ANALYSIS_D
ATA_DIR+ "/stopwords_utf8.txt");
Analyzer analyzer = new ChineseAnalyzer(stopWords);
return analyzer.tokenStream(field, reader);
第三,修改NutchAnalysis.jj文件。将|<SIGRAM: <CJK >>改为|< SIGRAM:
(<CJK>)+>,再用JavaCC 编译NutchAnalysis.jj这个文件,将生成的7个文件覆盖analysis包相应内容。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhujyy110/article/details/7781997

智能推荐

NAT(地址转换技术)详解_nat技术-程序员宅基地

文章浏览阅读10w+次,点赞418次,收藏1.7k次。目录NAT产生背景ip地址基础知识NAT技术的工作原理和特点静态NAT动态NATNAT重载(经常应用到实际中)NAT技术的优缺点优点缺点NAT穿越技术应用层网关(ALG)ALG的实际应用NAT技术的未来参考文献NAT产生背景今天,无数快乐的互联网用户在尽情享受Internet带来的乐趣。他们浏览新闻,搜索资料,下载软件,广交新朋,分..._nat技术

ACM 组队经验谈_acm 竞赛 题目 组队技巧-程序员宅基地

文章浏览阅读8.3k次,点赞5次,收藏12次。原本是ppt上面的,趴了下来,提醒自己。§序章——团队!ACM不是一个人的战斗§上篇——合理分工,演好自己的角色§下篇——队友齐心,其利断金§番外——深呼吸§尾声——信任与成功这个世界上大牛无处不在大牛的形成无非三种: 天赋异禀 勤奋过人 媳妇熬成婆大牛往往神功盖世,知道无数优化算法, coding_acm 竞赛 题目 组队技巧

说说如何在 Linux 中离线安装 Nginx_nginx linux aarch64 离线安装编译-程序员宅基地

文章浏览阅读317次。(1)下载并安装依赖包首先下载nginx-and-gcc.tar.gz,点击下载,该压缩包内包含了 Nginx-1.18.0以及 Nginx所需要的依赖库。依赖库主要为:编译 Nginx 的GCC 编译器;未来使用 C++ 来编写 Nginx 的 G++ 编译器;Perl 正则表达式(Nginx HTTP 模块依赖库);zlib (网络数据包 gzip压缩依赖库);openssl (提供HTTPS 支持以及 MD5、SHA1 等加密算法_nginx linux aarch64 离线安装编译

计算机网络复习------TCP的滑窗_往返时延 rtoa-程序员宅基地

文章浏览阅读320次。RTT和RTORTT(Round-Trip Time)往返时延:发送一个数据包到收到对应的ACK,所花费的时间。简单来说就是我发送一个数据包,然后对端回发一个ACK,当接我收到ACK之后,就能计算出从我发出包到接到回应过了多久,这个时间就是RTT。RTT计算就是一个时间差RTO(Rnsmission time-out)重传间隔:重传时间间隔TCP在发送一个数据包之后,会启动一个重传..._往返时延 rtoa

codeforce Anton and Fairy Tale-程序员宅基地

文章浏览阅读432次。题意:有一个谷仓,它的容量为N。第i天先会增加M(不会超出它的容量),然后减少i, 问第几天后谷仓为空,且第一天谷仓是满的。第i天 增加 减少 1 0 1 2 1

使用VS2019进行python开发 调试 环境创建_vs2019 python调试-程序员宅基地

文章浏览阅读2.1k次,点赞2次,收藏25次。VS作为宇宙第一编辑器,对Python开发也有很好的支持。添加安装打开Visual Studio Installer点击修改勾选python以及用于科学分析脚本简单使用新建一个python项目选择Python环境查看Python环境添加Python环境可以选择当前已经有的环境,或者创建新的环境.常用的调试快捷键F5 F9 F10 F11这些vs常用的调试快捷键都是可以用的几个有用的窗口打开python调试交互窗口菜单:调试->窗口->python调试交_vs2019 python调试

随便推点

PriorityQueue优先级队列_priorityqueue默认-程序员宅基地

文章浏览阅读963次,点赞15次,收藏8次。PriorityQueue优先级队列_priorityqueue默认

JobClient_jobclient getjob null-程序员宅基地

文章浏览阅读926次。+18投票我是想收集一些作业跟踪中的信息。 对于初学者来说, 我想开始让正在运行的作业信息如作业id或者工作名称等。 但已经跑了, 下面是我有什么( 将打印出当前运行作业的作业id )public static void main(String[] args) throws IOException { Configuration co_jobclient getjob null

Cisco(GNS3) - 数据链路层协议PPP_gns3ppp协议-程序员宅基地

文章浏览阅读2.5k次,点赞3次,收藏22次。PPP(Point to Point Protocol)广域网点对点串行链路上的封装协议,相比HDLC(High-Level Data Link Control)协议具有更好的扩展功能,例如数据压缩、身份验证、链路捆绑等。PPP基本配置(Authentication) PPP身份认证(PAP) PPP身份认证(CHAP) PPP链路捆绑(MultiLink)一: PPP基本配置..._gns3ppp协议

JAVA1.8新特性_java 1.8 annotation 的作用域 use_type和type_parameter-程序员宅基地

文章浏览阅读215次。“Java is still not dead—and people are starting to figure that out.”本教程将用带注释的简单代码来描述新特性,你将看不到大片吓人的文字。一、接口的默认方法Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下:复制代码代码如下:_java 1.8 annotation 的作用域 use_type和type_parameter

Ubuntu系统下安装gnome桌面_ubuntu启动gnome桌面-程序员宅基地

文章浏览阅读8.9k次。sudo apt-get install gnome-shell_ubuntu启动gnome桌面

mysql 个别字段设置默认值_mysql laravel 给某个字段设置默认值-程序员宅基地

文章浏览阅读1.4k次。项目中经常遇到一些问题:添加到表中数据一般不会出现什么错误,反而读取数据各种报错像我这种,自以为很简单的读取,也不debug,直接获取数据,然后。。非常浪费时间,有个别报错。查看的时候,原来是某个字段为空 转化 数据类型的出现错误。解决办法:那就是‘设置默认值’我试过在实体里添加默认值 没有效果数据库---找到数据表-修改字段默认值--存入数据的时候还是没有效果..._mysql laravel 给某个字段设置默认值