【问题标题】:Tokenize, remove stop words using Lucene with Java使用 Lucene 和 Java 标记、删除停用词
【发布时间】:2013-07-11 14:44:31
【问题描述】:

我正在尝试使用 Lucene 从 txt 文件中标记和删除停用词。我有这个:

public String removeStopWords(String string) throws IOException {

Set<String> stopWords = new HashSet<String>();
    stopWords.add("a");
    stopWords.add("an");
    stopWords.add("I");
    stopWords.add("the");

    TokenStream tokenStream = new StandardTokenizer(Version.LUCENE_43, new StringReader(string));
    tokenStream = new StopFilter(Version.LUCENE_43, tokenStream, stopWords);

    StringBuilder sb = new StringBuilder();

    CharTermAttribute token = tokenStream.getAttribute(CharTermAttribute.class);
    while (tokenStream.incrementToken()) {
        if (sb.length() > 0) {
            sb.append(" ");
        }
        sb.append(token.toString());
    System.out.println(sb);    
    }
    return sb.toString();
}}

我的主要看起来像这样:

    String file = "..../datatest.txt";

    TestFileReader fr = new TestFileReader();
    fr.imports(file);
    System.out.println(fr.content);

    String text = fr.content;

    Stopwords stopwords = new Stopwords();
    stopwords.removeStopWords(text);
    System.out.println(stopwords.removeStopWords(text));

这给了我一个错误,但我不知道为什么。

【问题讨论】:

  • 您看到的错误是什么?
  • 它抱怨 while (tokenStream.incrementToken())

标签: java lucene nlp tokenize stop-words


【解决方案1】:

Lucene 发生了变化,因此建议的答案(发布于 2014 年)将无法编译。这是与 Lucene 8.6.3 和 Java 8 一起使用的代码 @user1050755 的略微修改版本:

final String text = "This is a short test!"
final List<String> stopWords = Arrays.asList("short","test"); //Filters both words
final CharArraySet stopSet = new CharArraySet(stopWords, true);

try {
    ArrayList<String> remaining = new ArrayList<String>();

    Analyzer analyzer = new StandardAnalyzer(stopSet); // Filters stop words in the given "stopSet"
    //Analyzer analyzer = new StandardAnalyzer(); // Only filters punctuation marks out of the box, you have to provide your own stop words!
    //Analyzer analyzer = new EnglishAnalyzer(); // Filters the default English stop words (see link below)
    //Analyzer analyzer = new EnglishAnalyzer(stopSet); // Only uses the given "stopSet" but also runs a stemmer, so the result might not look like what you expected.
    
    TokenStream tokenStream = analyzer.tokenStream(CONTENTS, new StringReader(text));
    CharTermAttribute term = tokenStream.addAttribute(CharTermAttribute.class);
    tokenStream.reset();

    while(tokenStream.incrementToken()) {
        System.out.print("[" + term.toString() + "] ");
        remaining.add(term.toString());
    }

    tokenStream.close();
    analyzer.close();
} catch (IOException e) {
    e.printStackTrace();
}

您可以在官方Github (here) 上找到 EnglishAnalyzer 的默认停用词。

打印结果:

  • StandardAnalyzer(stopSet): [this] [is] [a]
  • StandardAnalyzer(): [this] [is] [a] [short] [test]
  • EnglishAnalyzer(): [this] [short] [test]
  • EnglishAnalyzer(stopSet): [thi] [is] [a] (不,这不是错字,它确实输出了thi!)

可以将默认停用词和您自己的停用词结合使用,但最好使用CustomAnalyzer(查看this answer)。

【讨论】:

    【解决方案2】:

    我有同样的问题。要使用Lucene 删除停用词,您可以使用EnglishAnalyzer.getDefaultStopSet(); 方法使用它们的默认停止集。否则,您可以创建自己的自定义停用词列表。

    下面的代码显示了您的removeStopWords() 的正确版本:

    public static String removeStopWords(String textFile) throws Exception {
        CharArraySet stopWords = EnglishAnalyzer.getDefaultStopSet();
        TokenStream tokenStream = new StandardTokenizer(Version.LUCENE_48, new StringReader(textFile.trim()));
    
        tokenStream = new StopFilter(Version.LUCENE_48, tokenStream, stopWords);
        StringBuilder sb = new StringBuilder();
        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
        tokenStream.reset();
        while (tokenStream.incrementToken()) {
            String term = charTermAttribute.toString();
            sb.append(term + " ");
        }
        return sb.toString();
    }
    

    要使用自定义停用词列表,请使用以下内容:

    //CharArraySet stopWords = EnglishAnalyzer.getDefaultStopSet(); //this is Lucene set 
    final List<String> stop_Words = Arrays.asList("fox", "the");
    final CharArraySet stopSet = new CharArraySet(Version.LUCENE_48, stop_Words, true);
    

    【讨论】:

    • 需要哪些导入才能使上述代码正常工作?
    • @user1050755 链接的EnglishAnalyzer 版本有效,但StandardAnalyzer 不会删除任何单词,因为您可能必须给它一个停用词列表。你是怎样做的?也请将此代码作为答案发布,因为上面的其他代码已经过时并且不再适用于更高版本的 Lucene(我使用的是 8.6.3)。
    【解决方案3】:

    您可以在调用 tokenStream.incrementToken() 之前尝试调用 tokenStream.reset()

    【讨论】:

      猜你喜欢
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-25
      • 1970-01-01
      • 1970-01-01
      • 2016-05-21
      • 1970-01-01
      相关资源
      最近更新 更多