从大文本文件中过滤停用词(使用软件包:nltk.corpus)

时间:2019-06-04 01:26:07

标签: python

我正在尝试在大型文本文件中对最常用的单词进行排名--爱丽丝与仙境(这是公共领域)。这是DropboxPastebin上的《爱丽丝梦游仙境》。它可以正常运行,并且有1818个“ the”实例和940个“ and”实例。

但是,现在在我的脚本的最新迭代中,我试图过滤出最常用的词,例如“和”,“那里”,“那个”,“那个”,“到”,“一个”等等。那里的任何搜索算法都会搜索类似的单词(在SEO术语中称为stop words),并将其从查询中排除。我为此任务导入的Python库为nltk.corpus

当我生成停用词列表并调用过滤器时,“ the”和“ of”的所有实例都会按预期被过滤掉,但不会捕获“ and”或“ you”。我不清楚为什么。

我尝试通过手动并显式添加出现在输出中不应该出现的单词来增强停用词列表。我添加了“ said”,“ you”,“ that”和其他名称,但它们仍显示为文本文件中最常见的10个词之一。

这是我的剧本:

from collections import Counter
from nltk.corpus import stopwords
import re

def open_file():
   with open('Alice.txt') as f:
       text = f.read().lower()
   return text

def main(text):
   stoplist = stopwords.words('english') # Bring in the default English NLTK stop words
   stoplist.extend(["said", "i", "it", "you", "and","that",])
   # print(stoplist)
   clean = [word for word in text.split() if word not in stoplist]
   clean_text = ' '.join(clean)
   words = re.findall('\w+', clean_text)
   top_10 = Counter(words).most_common(10)
   for word,count in top_10:
       print(f'{word!r:<4} {"-->":^4} {count:>4}')

if __name__ == "__main__":
   text = open_file()
   main(text)

这是我的实际输出:

  

$ python script8.py

     

'alice'-> 403

     

'i'-> 283

     

'it'-> 205

     

's--184

     

'小'-> 128

     

'你'-> 115

     

'和'-> 107

     

'one'-> 106

     

'古腾堡'-> 93

     

'that'-> 92

我期望将“ i”,“ it”和“ you”的所有实例排除在此列表之外,但它们仍在出现,我不清楚为什么。

2 个答案:

答案 0 :(得分:2)

您的代码会执行以下操作:

  1. 首先,您使用text.split()在空白处分割文本。但是生成的“单词”列表仍然包括标点符号,例如as,head!''i(请注意,'用作引号和撇号)。

  2. 然后,您排除stopwords中具有匹配项的所有“单词”。这将排除i,但不排除'i

  3. 接下来,您将所有其余的单词都用空格重新加入。

  4. 然后,您使用'\w+'正则表达式搜索字母序列(不包括标点符号):因此'i将与i匹配。这就是is出现在前10名中的原因。

有几种方法可以解决此问题。例如,您可以使用re.split()分割多个空格:

def main(text):
   stoplist = stopwords.words('english')
   stoplist.extend(["said"]) # stoplist already includes "i", "it", "you"
   clean = [word for word in re.split(r"\W+", text) if word not in stoplist]
   top_10 = Counter(clean).most_common(10)
   for word,count in top_10:
       print(f'{word!r:<4} {"-->":^4} {count:>4}')

输出:

'alice' -->   403
'little' -->   128
'one' -->   106
'gutenberg' -->    93
'know' -->    88
'project' -->    87
'like' -->    85
'would' -->    83
'went' -->    83
'could' -->    78

请注意,这将分别处理带连字符的短语:因此gutenberg-tm-> gutenbergtm。要对此进行更多控制,您可以遵循Jay's的建议并查看nltk.tokenize。例如,nltk令牌生成器知道收缩,因此don't-> do + n't

您还可以通过从文本中删除Gutenberg许可条件来改善事情:)

答案 1 :(得分:1)

例如:

"it's".split() >> [是]

re.findall('\w+', "it's") >> [它,s]

这就是为什么“停止列表”不会像您想的那样。

修复:

def main(text):
    words = re.findall('\w+', text)
    counter = Counter(words)
    stoplist = stopwords.words('english')
    #stoplist.extend(["said", "i", "it", "you", "and", "that", ])
    stoplist.extend(["said", "i", "it", "you"])
    [stoplist.remove(keep_word) for keep_word in ['s', 'and', 'that']]
    for stop_word in stoplist:
        del counter[stop_word]
    for word, count in counter.most_common(10):
        print(f'{word!r:<4} {"-->":^4} {count:>4}')

输出

'and' -->   940
'alice' -->   403
'that' -->   330
's'  -->   219
'little' -->   128
'one' -->   106
'gutenberg' -->    93
'know' -->    88
'project' -->    86
'like' -->    85

注意:"i", "it" and "you" to be excluded from your list