`

Lucene中文分词

阅读更多
发布日期:2006年07月10日,更新日期:2006年07月30日
Apache Lucene作为一个开放源码的搜索软件包应用越来越广泛,但是对于中文用户来说其提供的两个中文分词器(CJKAnalyzer、ChineseAnalyzer)的功能又太弱了。所以迫切需要开发自己的中文分词器,而开发适用的分词器是一项很有挑战的工作。我想在文章中实现一个中文分词器,让它实现机械分词中最简单的算法--正向最大匹配法。目前普遍认为这一算法的错分率为1/169,虽然这不是一个精确的分词算法,但是它的实现却很简单。我想它已经可以满足一些项目的应用了。这一算法是依赖于词库的,词库的好坏对于错分率有重要影响,因此还想介绍一个词库。

这篇文章的内容质量不是很高,您可以在这里找到更新后的版本。Solo L正在努力提高这里所提供的内容的质量。如果由于内容的质量问题给您造成了影响,我在此真诚的表示歉意!

什么是中文分词

众所周知,英文是以词为单位的,词和词之间是靠空格隔开,而中文是以字为单位,句子中所有的字连起来才能描述一个意思。例如,英文句子I am a student,用中文则为:“我是一个学生”。计算机可以很简单通过空格知道student是一个单词,但是不能很容易明白“学”、“生”两个字合起来才表示一个词。把中文的汉字序列切分成有意义的词,就是中文分词,有些人也称为切词。我是一个学生,分词的结果是:我 是 一个 学生。

中文分词技术

现有的分词技术可分为三类:

  • 基于字符串匹配的分词
  • 基于理解的分词
  • 基于统计的分词

这篇文章中使用的是基于字符串匹配的分词技术,这种技术也被称为机械分词。它是按照一定的策略将待分析的汉字串与一个“充分大的”词库中的词条进行匹配。若在词库中找到某个字符串则匹配成功(识别出一个词)。按照扫描方向的不同,串匹配分词方法可以分为正向匹配和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词法和分词与标注结合法。常用的几种机械分词方法如下:

  • 正向最大匹配法(由左到右的方向)
  • 逆向最大匹配法(由右到左的方向)

分词器实现

这个实现了机械分词中正向最大匹配法的Lucene分词器包括两个类,CJKAnalyzer和CJKTokenizer,他们的源代码如下:

package org.solol.analysis;

import java.io.Reader;
import java.util.Set;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.StopFilter;
import org.apache.lucene.analysis.TokenStream;

/**
 * @author solo L
 * 
 */
public class CJKAnalyzer extends Analyzer {//实现了Analyzer接口,这是lucene的要求
    public final static String[] STOP_WORDS = {};
    
    private Set stopTable;    

    public CJKAnalyzer() {
        stopTable = StopFilter.makeStopSet(STOP_WORDS);
    }

    @Override
    public TokenStream tokenStream(String fieldName, Reader reader) {
        return new StopFilter(new CJKTokenizer(reader), stopTable);
    }    
}    
package org.solol.analysis;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.TreeMap;

import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.Tokenizer;

/**
 * @author solo L
 * 
 */
public class CJKTokenizer extends Tokenizer {
    //这个TreeMap用来缓存词库
    private static TreeMap simWords = null;

    private static final int IO_BUFFER_SIZE = 256;

    private int bufferIndex = 0;

    private int dataLen = 0;

    private final char[] ioBuffer = new char[IO_BUFFER_SIZE];

    private String tokenType = "word";

    public CJKTokenizer(Reader input) {
        this.input = input;
    }

    //这里是lucene分词器实现的最关键的地方
    public Token next() throws IOException {
        loadWords();

        StringBuffer currentWord = new StringBuffer();

        while (true) {
            char c;
            Character.UnicodeBlock ub;

            if (bufferIndex >= dataLen) {
                dataLen = input.read(ioBuffer);
                bufferIndex = 0;
            }

            if (dataLen == -1) {
                if (currentWord.length() == 0) {
                    return null;
                } else {
                    break;
                }
            } else {
                c = ioBuffer[bufferIndex++];                
                ub = Character.UnicodeBlock.of(c);
            }
            //通过这个条件不难看出这里只处理了CJK_UNIFIED_IDEOGRAPHS,
            //因此会丢掉其它的字符,如它会丢掉LATIN字符和数字
            //这也是该lucene分词器的一个限制,您可以在此基础之上完善它,
            //也很欢迎把您完善的结果反馈给我
            if (Character.isLetter(c) && ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS) {
                tokenType = "double";
                if (currentWord.length() == 0) {
                    currentWord.append(c);                    
                } else {
                    //这里实现了正向最大匹配法
                    String temp = (currentWord.toString() + c).intern();
                    if (simWords.containsKey(temp)) {
                        currentWord.append(c);                        
                    } else {
                        bufferIndex--;
                        break;
                    }
                }
            }
        }
        Token token = new Token(currentWord.toString(), bufferIndex - currentWord.length(), bufferIndex, tokenType);
        currentWord.setLength(0);
        return token;
    }
    //装载词库,您必须明白它的逻辑和之所以这样做的目的,这样您才能理解正向最大匹配法是如何实现的
    public void loadWords() {
        if (simWords != null)return;
        simWords = new TreeMap();

        try {
            InputStream words = new FileInputStream("simchinese.txt");
            BufferedReader in = new BufferedReader(new InputStreamReader(words,"UTF-8"));
            String word = null;

            while ((word = in.readLine()) != null) {
                //#使得我们可以在词库中进行必要的注释
                if ((word.indexOf("#") == -1) && (word.length() < 5)) {
                    simWords.put(word.intern(), "1");
                    if (word.length() == 3) {
                        if (!simWords.containsKey(word.substring(0, 2).intern())) {
                            simWords.put(word.substring(0, 2).intern(), "2");
                        }
                    }
                    if (word.length() == 4) {
                        if (!simWords.containsKey(word.substring(0, 2).intern())) {
                            simWords.put(word.substring(0, 2).intern(), "2");
                        }
                        if (!simWords.containsKey(word.substring(0, 3).intern())) {
                            simWords.put(word.substring(0, 3).intern(), "2");
                        }

                    }
                }
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

分词效果

这是我在当日的某新闻搞中随意选的一段话:
此外,巴黎市政府所在地和巴黎两座体育场会挂出写有相同话语的巨幅标语,这两座体育场还安装了巨大屏幕,以方便巴黎市民和游客观看决赛。

分词结果为:
此外 巴黎 市政府 所在地 和 巴黎 两座 体育场 会 挂出 写有 相同 话语 的 巨幅 标语 这 两座 体育场 还 安装 了 巨大 屏幕 以 方便 巴黎 市民 和 游客 观看 决赛

提示

这个lucene分词器还比较脆弱,要想将其用于某类项目中您还需要做一些工作,不过我想这里的lucene分词器会成为您很好的起点。

参考资料
  • MMSeg是一个开放源代码的中文分词软件包,可以方便的和Lucene集成。它实现了MMSEG: A Word Identification System for Mandarin Chinese Text Based on Two Variants of the Maximum Matching Algorithm算法。

  • Apache Lucene
solo L 一位有些理想主义的软件工程师,创建了solol.org。他常常在这里发表一些对技术的见解。
分享到:
评论

相关推荐

    Lucene中文分词器包

    来自“猎图网 www.richmap.cn”基于IKAnalyzer分词算法的准商业化Lucene中文分词器。 1. 正向全切分算法,42万汉字字符/每秒的处理能力(IBM ThinkPad 酷睿I 1.6G 1G内存 WinXP) 2. 对数量词、地名、路名的...

    Lucene中文分词器组件

    本文将深入探讨Lucene中文分词器组件的相关知识点。 首先,我们要明白中文分词的重要性。由于中文是以词为基本单位,不像英文那样有明显的空格分隔,因此在进行信息检索时,需要先对中文文本进行分词,将连续的汉字...

    lucene中文分词工具包

    Lucene是一个高性能、全文检索库,而“lucene中文分词工具包”则为Lucene提供了一个专门针对中文分词的解决方案。这个工具包的核心是IKAnalyzer,它是一个开源且基于Java语言开发的轻量级中文分词工具,旨在提升中文...

    lucene中文分词器(paoding解牛)

    《Lucene中文分词器——Paoding解牛详解》 在中文信息检索领域,分词是至关重要的一环,它能够将连续的汉字序列切割成具有独立意义的词语,为后续的索引和查询提供基础。Lucene作为Java最著名的全文搜索引擎库,其...

    lucene.NET 中文分词

    中文分词是将连续的汉字序列切分成具有语义的词语的过程,是自然语言处理(NLP)中的基础步骤。在Lucene.NET中,为了支持中文分词,通常需要结合第三方分词器,如IK Analyzer、HanLP、jieba.NET等。这些分词器具备...

    Lucene中文分词组件 JE-Analysis 1.5.1

    //采用正向最大匹配的中文分词算法,相当于分词粒度等于0 MMAnalyzer analyzer = new MMAnalyzer(); //参数为分词粒度:当字数等于或超过该参数,且能成词,该词就被切分出来 MMAnalyzer analyzer = new ...

    lucene中文分词

    《Lucene中文分词技术详解》 在信息检索和自然语言处理领域,中文分词是至关重要的一步。Lucene,作为一个强大的全文搜索引擎库,对于处理中文文档,分词的准确性和效率直接影响到搜索效果。本文将围绕“lucene中文...

    lucene 中文分词 庖丁解牛

    《Lucene中文分词:庖丁解牛》 在信息技术高速发展的今天,全文搜索引擎已经成为网站内容检索不可或缺的一部分。其中,Apache Lucene作为一个开源的全文检索库,被广泛应用于各种项目中,尤其对于处理中文文本,...

    lucene中文分词jar包

    关于lucene中文分词的一个辅助jar包

    lucene中文分词源码,做搜索引擎需要用到的好东西哦

    《深入理解Lucene中文分词源码:打造高效搜索引擎》 在信息爆炸的时代,搜索引擎已经成为了我们获取知识的重要工具。而构建一个强大的搜索引擎,离不开核心的文本处理技术——中文分词。Lucene作为一款高性能、全文...

    lucene中文分词(庖丁解牛)庖丁分词

    《Lucene中文分词——庖丁解牛》 在自然语言处理领域,中文分词是基础且关键的一环。在Java开发中,Apache Lucene是一个强大的全文搜索引擎库,但默认并不支持中文,这就需要借助第三方分词工具。本文将深入探讨...

    lucene中文分词公用组件V1.4

    《深入理解Lucene中文分词公用组件V1.4》 Lucene,作为一个强大的全文搜索引擎库,对于中文处理尤其重要,而中文分词是其中的关键环节。本文将深入解析Lucene中文分词公用组件V1.4的更新内容,帮助开发者更好地理解...

    基于词典的最大匹配的Lucene中文分词程序

    本文将深入探讨“基于词典的最大匹配”的Lucene中文分词程序,这是构建高效、准确的中文信息处理系统的重要组成部分。 首先,我们要理解什么是分词。中文分词是指将连续的汉字序列按照词语的边界进行划分,使得每个...

    引入局部统计识别高频词汇的Lucene中文分词程序STUSegmentConfig.rar

    标题中的“引入局部统计识别高频词汇的Lucene中文分词程序STUSegmentConfig.rar”表明这是一个基于Lucene的中文分词工具,它利用了局部统计信息来识别和处理中文文本中的高频词汇。Lucene是一个开源全文检索库,广泛...

    引入局部统计识别高频词汇的Lucene中文分词程序src.rar

    标题中的“引入局部统计识别高频词汇的Lucene中文分词程序src.rar”表明这是一个关于使用Lucene进行中文分词的源代码项目,其中融入了局部统计的方法来识别和处理高频词汇。Lucene是一个流行的全文检索库,广泛应用...

    Struts标签Lucene中文分词构建

    ### Struts标签Lucene中文分词构建 #### 概述 本文主要介绍如何利用Struts框架中的标签来实现中文分词的功能,特别是基于Lucene的分析器进行分词处理,并结合Log4j进行日志记录的技术实践。Struts作为Apache ...

    lucene3庖丁解牛中文分词器

    《深入剖析:Lucene3与庖丁解牛中文分词器》 在信息技术飞速发展的今天,全文检索和搜索引擎已经成为日常开发中不可或缺的部分。Lucene作为一款强大的全文检索库,被广泛应用于各种信息检索系统中。然而,对于中文...

    IKAnalyzer2012+lucene中文分词

    IKAnalyzer2012+lucene中文分词是一个用于搜索引擎或信息检索系统的中文处理工具,它结合了IKAnalyzer2012和lucene-core-3.6.0这两个关键组件,为处理中文文本提供了高效的分词服务。在这个组合中,IKAnalyzer是主要...

    lucene中文分词公用组件V1.3

    1.修正了1.2版本在数量词处理的缺陷 2.优化分词性能 3.优化词典 请参考lucene中文分词公用组件V1.2之前版本使用说明

    lucene 中文分词

    **Lucene 中文分词** Lucene 是一个开源的...总的来说,通过这个简单的Lucene中文分词案例,你可以了解到如何利用Lucene进行全文检索,并结合第三方分词器处理中文内容,从而在Java项目中实现高效的中文搜索功能。

Global site tag (gtag.js) - Google Analytics