Lucene使用(四)中文分词器smartcn

时间:2021-06-10 03:09:10
Lucene自带多种分词器,其中对中文分词支持比较好的是smartcn。

1. 标准分词器StandardAnalyzer

在演示smartcn中文分词器之前,先来看看Lucene标准分词器对中文分词的效果。需要的jar为\lucene-5.5.5\core\下的lucene-core-5.5.5.jar和\lucene-5.5.5\analysis\common\下的lucene-analyzers-common-5.5.5.jar。新建测试类TestLucene04:
package net.xxpsw.demo.lucene.test;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
public class TestLucene04 {
	private void print(Analyzer analyzer) throws Exception {
		String text = "Lucene自带多种分词器,其中对中文分词支持比较好的是smartcn。";
		TokenStream tokenStream = analyzer.tokenStream("content", text);
		CharTermAttribute attribute = tokenStream.addAttribute(CharTermAttribute.class);
		tokenStream.reset();
		while (tokenStream.incrementToken()) {
			System.out.println(new String(attribute.toString()));
		}
	}
}
增加测试方法testStandardAnalyzer:
	/**
	* @Description: 测试标准分词器
	* @throws Exception
	 */
	@Test
	public void testStandardAnalyzer() throws Exception {
		StandardAnalyzer standardAnalyzer = new StandardAnalyzer();
		print(standardAnalyzer);
	}
执行测试,控制台打印结果如下:
Lucene使用(四)中文分词器smartcn
由上可见,标准分词器对中文的分词结果是分成了单个汉字,而并没有识别常用的汉语词组。

2. 中文分词器SmartChineseAnalyzer

引入\lucene-5.5.5\analysis\smartcn\下的lucene-analyzers-smartcn-5.5.5.jar,新增测试方法testSmartChineseAnalyzer:
	/**
	* @Description: 测试中文分词器
	* @throws Exception
	 */
	@Test
	public void testSmartChineseAnalyzer() throws Exception {
		SmartChineseAnalyzer smartChineseAnalyzer = new SmartChineseAnalyzer();
		print(smartChineseAnalyzer);
	}
执行测试方法,控制台打印结果如下:
Lucene使用(四)中文分词器smartcn
从上述打印结果中可以看到,“多种”、“分词”、“其中”、“中文”、“支持”、“比较”等中文词组都被顺利的识别出来。
进入SmartChineseAnalyzer源码中可以看到如下代码:

  public SmartChineseAnalyzer() {
    this(true);
  }
查看this(true):
  public SmartChineseAnalyzer(boolean useDefaultStopWords) {
    stopWords = useDefaultStopWords ? DefaultSetHolder.DEFAULT_STOP_SET
      : CharArraySet.EMPTY_SET;
  }
查看DefaultSetHolder.DEFAULT_STOP_SET:
  private static class DefaultSetHolder {
    static final CharArraySet DEFAULT_STOP_SET;

    static {
      try {
        DEFAULT_STOP_SET = loadDefaultStopWordSet();
      } catch (IOException ex) {
        // default set should always be present as it is part of the
        // distribution (JAR)
        throw new RuntimeException("Unable to load default stopword set");
      }
    }

    static CharArraySet loadDefaultStopWordSet() throws IOException {
      // make sure it is unmodifiable as we expose it in the outer class
      return CharArraySet.unmodifiableSet(WordlistLoader.getWordSet(IOUtils
          .getDecodingReader(SmartChineseAnalyzer.class, DEFAULT_STOPWORD_FILE,
              StandardCharsets.UTF_8), STOPWORD_FILE_COMMENT));
    }
  }
查看DEFAULT_STOPWORD_FILE:
private static final String DEFAULT_STOPWORD_FILE = "stopwords.txt";
可见SmartChineseAnalyzer的空构造函数实际上默认加载了一个停用词列表文件stopwords.txt,该文件在jar包中的位置如下:
Lucene使用(四)中文分词器smartcn
该文件中包含了53个需要停用的标点符号,分别是,.`-_=?'|"(){}[]<>*#&^$@!~:;+/\《》—-,。、:;!·?“”)(【】[]●及中文空格。

3. 自定义停用词

SmartChineseAnalyzer还支持自定义停用词,新建测试方法testMySmartChineseAnalyzer:
	/**
	* @Description: 测试自定义停用词
	* @throws Exception
	 */
	@Test
	public void testMySmartChineseAnalyzer() throws Exception {
		CharArraySet charArraySet = new CharArraySet(0, true);

		// 系统默认停用词
		Iterator<Object> iterator = SmartChineseAnalyzer.getDefaultStopSet().iterator();
		while (iterator.hasNext()) {
			charArraySet.add(iterator.next());
		}

		// 自定义停用词
		String[] myStopWords = { "对", "的", "是", "其中" };
		for (String stopWord : myStopWords) {
			charArraySet.add(stopWord);
		}

		SmartChineseAnalyzer smartChineseAnalyzer = new SmartChineseAnalyzer(charArraySet);
		print(smartChineseAnalyzer);
	}
}
执行测试方法,控制台打印如下:
Lucene使用(四)中文分词器smartcn
对比测试方法testSmartChineseAnalyzer可以看出,"对", "的", "是", "其中"等中文词已被停用而不再出现。