我是python的新手。我得到一个包含大约2000个文本文件的文件夹。我应该输出每个单词及其出现次数(不重复文件)。例如,句子:“我就是我”必须在文件中只包含一次“i”。
我能够为单个文件执行此操作,但如何为多个文件执行此操作?
from collections import Counter
import re
def openfile(filename):
fh = open(filename, "r+")
str = fh.read()
fh.close()
return str
def removegarbage(str):
# Replace one or more non-word (non-alphanumeric) chars with a space
str = re.sub(r'\W+', ' ', str)
str = str.lower()
return str
def getwordbins(words):
cnt = Counter()
for word in words:
cnt[word] += 1
return cnt
def main(filename, topwords):
txt = openfile(filename)
txt = removegarbage(txt)
words = txt.split(' ')
bins = getwordbins(words)
for key, value in bins.most_common(topwords):
print key,value
main('speech.txt', 500)
答案 0 :(得分:4)
您可以使用glob
模块中的glob()
或iglob()
功能获取文件列表。我注意到您没有有效地使用Counter
对象。最好只调用它的update()
方法并将其传递给单词列表。这是一个简化的代码版本,用于处理指定文件夹中找到的所有*.txt
文件:
from collections import Counter
from glob import iglob
import re
import os
def remove_garbage(text):
"""Replace non-word (non-alphanumeric) chars in text with spaces,
then convert and return a lowercase version of the result.
"""
text = re.sub(r'\W+', ' ', text)
text = text.lower()
return text
topwords = 100
folderpath = 'path/to/directory'
counter = Counter()
for filepath in iglob(os.path.join(folderpath, '*.txt')):
with open(filepath) as file:
counter.update(remove_garbage(file.read()).split())
for word, count in counter.most_common(topwords):
print('{}: {}'.format(count, word))
答案 1 :(得分:2)
请参阅os.listdir()
,它将为您提供目录中所有条目的列表。
答案 2 :(得分:2)
如果我的解释正确,您希望为每个单词计算包含该单词的文件数。这是你能做的。
对于每个文件,在此文件中获取一组单词(即单词应该是唯一的)。然后,对于每个单词计数,可以找到它的集合数。
以下是我的建议:
os.listdir
来实现此目的。在此文件中找到一组单词:
with open(filepath, 'r') as f:
txt = removegarbage(f.read())
words = set(txt.split())
现在,当每个文件中都有一组单词时,您最终可以使用Counter
这些集合。最好使用其update
方法。这是一个小小的演示:
>>> a = set("hello Python world hello".split())
>>> a
{'Python', 'world', 'hello'}
>>> b = set("foobar hello world".split())
>>> b
{'foobar', 'hello', 'world'}
>>> c = Counter()
>>> c.update(a)
>>> c.update(b)
>>> c
Counter({'world': 2, 'hello': 2, 'Python': 1, 'foobar': 1})
答案 3 :(得分:0)
所以你可能会做一些类似的事情:
#!python
from __future__ import print_function
# Your code here
# ...
#
if __name__ == '__main__':
import sys
top=500
if len(sys.argv) < 2:
print ("Must supply a list of files to operate on", file=sys.stderr)
## For Python versions older than 2.7 use print >> sys.stderr, "..."
sys.exit(1)
for each in sys.argv[1:]:
main(each, top)
请注意,我正在展示一种简单的方法来包装现有函数,以便您可以使用任意数量的文件名参数调用程序。如果你想要,你也可以只用一个参数来指向你想要处理所有文件的目录:
#!python
from __future__ import print_function
# Your code here
# ...
#
if __name__ == '__main__':
import sys
top = 500
if len(sys.argv) != 2:
## Require exactly one argument: sys.argv[0] is our own executable filename
## (Similarly to how class methods are called with "self" as their first
## argument, but on the OS layer)
print ("Must supply directory name full of files to be processed", file=sys.stderr)
sys.exit(1)
for each in os.listdir(sys.argv[1]):
main(each, top)
还有很多其他方法可以选择处理你的参数,硬代码默认参数等等。我会让你想象一下如何将“顶层”从硬编码值改为命令行参数。对于额外的功劳,使用选项/ arg解析模块(argparse或optparse)使其成为带默认值的命令行开关。
请注意,此if __name__ == ....
商家是一种Python惯例,它通过鼓励您将功能与操作分开来促进良好的编程实践。因此,您可以在if __name__ == '__main__':
行之上定义所有功能,并且可以在其后调用脚本执行的所有操作(使用该功能)。这允许您的文件被其他程序用作模块,同时仍然允许它自己拥有自己的实用程序作为程序。 (这是一个几乎与Python无关的功能,尽管Ruby实现了一组类似的语义,但语法略有不同)。
__future__
内容允许您使用Python 2.7编写程序,该程序使用与Python 3.x兼容的print
语义。这对于最终转换到Python 3以及讨论语言非常有用,因此我们可以逐步淘汰旧的“print”作为语句并推广使用“print()”函数。如果您不关心细节,请不要担心。只是意识到差异是普遍存在的,必须是微不足道的。您将看到的绝大多数示例使用旧的打印语义,并且您将希望使用更新的,略微不兼容的语义。
(注意:在我最初的帖子中,我在from __future__ import
部分中有__main__
。特别是那些不起作用(通常Python __future__
导入应该在任何其他之前发生代码)。[我基本上试图理解这个想法,并且不想陷入Python2.x和Python3打印语义之间的差异。