# -*- coding: utf-8 -*-
"""
Created on Wed Mar 28 16:49:38 2018
@author: 47899
"""
import codecs
import os
import nltk
import math
import operator
from nltk.tokenize import WordPunctTokenizer
def participles(text): #分词函数
pattern = r"""(?x) # set flag to allow verbose regexps
(?:[A-Z]\.)+ # abbreviations, e.g. U.S.A.
|\d+(?:\.\d+)?%? # numbers, incl. currency and percentages
|\w+(?:[-']\w+)* # words w/ optional internal hyphens/apostrophe
|\.\.\. # ellipsis
|(?:[.,;"'?():-_`]) # special characters with meanings
"""
t=nltk.regexp_tokenize(text, pattern)
length=len(t)
for i in range(length):
t[i]=t[i].lower()
return t
def getridofsw(lis, swlist): # 去除文章中的停用词
afterswlis = []
for i in lis:
if str(i) in swlist:
continue
else:
afterswlis.append(str(i).lower())
return afterswlis
def fun(filepath): # 遍历文件夹中的所有文件,返回文件list
arr = []
for root, dirs, files in os.walk(filepath):
for fn in files:
arr.append(root+"\\"+fn)
return arr
def read(path): # 读取txt文件,并返回list
with codecs.open(path, 'r', 'ANSI') as f:
data=f.read()
return data
def readstop(path): # 读取txt文件,并返回list
f = open(path,encoding='ANSI' )
data = []
for line in f.readlines():
data.append(line)
return data
def getstopword(path): # 获取停用词表
swlis = []
for i in readstop(path):
outsw = str(i).replace('\n', '').lower()
swlis.append(outsw)
return swlis
def freqword(wordlis): # 统计词频,并返回字典
freword = {}
for i in wordlis:
if str(i) in freword:
count = freword[str(i)]
freword[str(i)] = count+1
else:
freword[str(i)] = 1
return freword
def corpus(filelist, swlist): # 建立语料库
alllist = []
for i in filelist:
afterswlis = getridofsw(participles(read(str(i))), swlist)
alllist.append(afterswlis)
return alllist
def tf_idf(wordlis, filelist, corpuslist): # 计算TF-IDF,并返回字典
outdic = {}
tf = 0
idf = 0
dic = freqword(wordlis)
#outlis = []
for i in set(wordlis):
tf = dic[str(i)]/len(wordlis) # 计算TF:某个词在文章中出现的次数/文章总词数
# 计算IDF:log(语料库的文档总数/(包含该词的文档数+1))
idf = math.log(len(filelist)/(wordinfilecount(str(i), corpuslist)+1))
tfidf = tf*idf # 计算TF-IDF
outdic[str(i)] = tfidf
orderdic = sorted(outdic.items(), key=operator.itemgetter(
1), reverse=True) # 给字典排序
return orderdic
def wordinfilecount(word, corpuslist): # 查出包含该词的文档数
count = 0 # 计数器
for i in corpuslist:
for j in i:
if word in set(j): # 只要文档出现该词,这计数器加1,所以这里用集合
#if j.__contains__(word):
count = count+1
else:
continue
return count
def befwry(lis): # 写入预处理,将list转为string
outall = ''
for i in lis:
ech = str(i).replace("('", '').replace("',", '\t').replace(')', '')
outall = outall+'\t'+ech+'\n'
return outall
def wry(txt, path): # 写入txt文件
f = codecs.open(path, 'a', 'ANSI')
f.write(txt)
f.close()
return path
def main():
swpath = r'D:\text\stop_words_eng.txt'#停用词表路径
swlist = getstopword(swpath) # 获取停用词表列表
#print(swlist)
filepath = r'D:\text\yuliao\1'
filelist = fun(filepath)
corpuslist = corpus(filelist, swlist)
#print(corpuslist)
outall = ''
wrypath = r'D:\text\result\TFIDF2.txt'
for i in filelist:
afterswlis = getridofsw(participles(read(str(i))), swlist) # 获取每一篇已经去除停用的词表
tfidfdic = tf_idf(afterswlis, filelist, corpuslist) # 计算TF-IDF
titleary = str(i).split('\\')
title = str(titleary[-1]).replace('utf8.txt', '')
echout = title+'\n'+befwry(tfidfdic)
print(title+' is ok!')
outall = outall+echout
print(wry(outall, wrypath)+' is ok!')
main()
老规矩,先把代码贴出。上一周信息内容安全老师让我们应python实现英文文本的预处理、并通过计算TF-IDF的值来提取英文的特征词。接下来介绍一下每个子函数的功能。
1、分词def participles():
这个函数主要是用于英语语句的分词,思想是按照正则表达式,用到了nltk库函数,返回的是所有英文的小写形式,为了方便后面的词频统计。
2、去除停用词函数 def getridofsw():
当我们把原始的英文文档分好词之后,返回的是所有单词的列表形式,在这里为了后面的计算结果更加接近文章的真实特征值,我们需要去除英语文本的停用词,停用词可以在CSDN上找的txt的文档,大家可以自行搜索一下。
3、返回目标文件夹下所有文档的地址列表 def fun()
主要运用了os库的os.walk功能,遍历文件夹下的所有文件路径。因为后面所用到的语料库txt文件非常的多,所以要一一遍历。
4、read和readstop
两个函数功能一样,都是读取txt文件的文本信息,但是因为停用词的txt文件是一行一个词,所以写了readstop来专门读取停用词。不过后来想想,也就没用到。
5、获取停用词表def getstopword():
按行将停用词txt文档的停用词转换为列表存储起来。
6、统计词频def freqword():
返回字典形式,统计每一篇文章中进行处理后单词出现的频数。
7、建立语料库def corpus():
将一篇文章作为列表的一个元素,然后将文件夹中所有的文章链接成一个列表。方便后面的统计单词出现的文档数。
8、计算TF-IDF的值tf-idf():
最后按照TF-IDF的值将词按照降序排列。
9、统计出现的文档数def wordinfilecount():
利用了两层循环,外层循环遍历所有的文档,内层循环遍历文档中的单词。利用了集合的方法,在这里还尝试使用了contain函数,但是效果不是特别的好,一方面对效率的提升作用不是特别大,另一方面部分结果出现了错误。
10、写入函数def befwry/wry():
进行了一些写入的预处理,然后写入到txt文档中。
使用了SCI.SPACE文件中的1000份语料,内容大部分与宇宙及空间技术有关。
这里选取了部分结果作为展示,可见特征词的提取是大致正确的。