最近好幾天都沒有更新博客,因為網絡設置崩了,然后各種扎心,最后還重裝電腦,而且還有一些軟件需要重新安裝或者配置,所以煩了好久,搞好電腦之后,老師又布置了一個任務,個人覺得很有趣--判別學校新聞是否是標題黨
雖然我不覺得老師的方法能夠很好地判別標題黨行為,但是也只能開干了!
第一步:通過爬蟲獲取學校新聞,這一部分已經在之前的文章中寫過,所以不在重復了,有點不同的是,因為從文本中提取內容列會出錯,有少數文章的內容沒有被全部提取,所以我在源代碼的基礎上改變了一下,生成了一個只存放內容的文件content.csv
第二步:(1)對文檔內容進行分詞,並且按照文檔數分別存放在不同的文檔,例如3454篇新聞就用3454份文檔來存放分詞后的內容,但是是可以直接用一個文檔來存放的,每篇文章只在文檔中占一行就行,分詞用結巴,不要用全模式,否則后面選擇的關鍵詞會有很多相同,另外下載百度停用詞表,在停用詞表中的詞語就不要寫入文件中,因為不能成為關鍵詞,如是、的、好
(2)使用TF-IDF算法進行關鍵詞提取,首先套一個循環,循環3454個文檔,然后按行讀取,之后各種燒腦。舉個例子:在文檔A中,有100個分詞后的詞語,通過集合去掉重復的之后還剩下80個,把這80個加到字典中,並且要計算這80個詞語在文檔A中各自出現的次數;然后輪到文檔B,首先判斷文檔B中的分詞詞語有哪些在字典中,在字典中的話就不加進字典,但是值VALUES加1,否則加入字典。這個太難說清楚了,還是自己去看看詳細介紹吧!
(3)根據TF-IDF算法得到每篇新聞權值前三的詞語,並且寫入文件中
第三步:(1)訓練相似度模型:這是個很陌生的知識,但是用了工具就很簡單了,原理就是存儲許多詞語,把他們分為向量,就像網絡一樣連在一起,把距離的遠近作為詞語之間的相似度,缺點就在於無法識別不在模型中的詞語相似度。可以去看看這兩個鏈接,非常詳細:https://blog.csdn.net/kaoyala/article/details/79090156;https://github.com/jsksxs360/Word2Vec
(2)把模型訓練好了之后就簡單了,把標題從新聞中提取出來,然后進行全模式分詞,對於第一個關鍵詞,與分詞后的標題逐個計算相似度,取最大相似度,然后再到第二個關鍵詞,最后把結果寫入文件中
下面附上源碼:
import jieba import math import re def word(): #第一步:文檔預處理:讀取文檔 -> 刪除不需要的字符(如回車符\n、制表符\t、空格等) # -> 轉換成unicode格式 -> 對文檔分詞 -> 轉換成utf-8格式寫入txt文檔 #讀取文檔 #由於使用TF-IDF方法提取關鍵詞,而且需要分析題目相似度,所以每篇文章生成一個文檔! with open('content.csv', 'r', newline='', encoding='utf-8')as col: j = 1 for i in col.readlines(): content=jieba.cut(i,cut_all=False) #結巴分詞精確模式 result=" ".join(content) #把generator轉換為字符串類型 result=re.compile('[\u4e00-\u9fa5]+').findall(result) # 轉換為列表並且去掉了那些數字3,4英文之類的 list1=[] #存儲去掉空格之后的列表 #導入停用詞表,並進行簡單清洗 list111 = [] #存儲停用詞表 with open('baidustop.txt', 'r', encoding='utf-8')as f: for i in f.readlines(): i = i.strip() #去掉換行符 list111.append(i) for i in result: if len(i)<=1 : #如果是空格或者單個字就去掉不要 continue elif i in list111: #如果在停用詞表里面就不要 continue else: list1.append(i) # 把分詞結果寫入TXT文檔中 with open('txt/TF-IDF'+str(j)+'.txt','a',encoding='utf-8')as file: for word in list1: file.write(word+'\n') j+=1 #為了文檔名字 def language(): #第二步:使用TF-IDF算法進行關鍵詞提取 dict2={} #存放語料庫,統計一個單詞在多少個文件中存在 for i in range(1,3455): with open('txt/TF-IDF' + str(i) + '.txt', 'r', encoding='utf-8')as file: list2=[] for wd in file.readlines(): #按行讀取 wd=wd.replace('\n','') #去掉換行符 list2.append(wd) #制作語料庫字典,為了求解IDF set1=set(list2) #轉換為集合! for word in set1: dict2[word]=dict2.get(word,0)+1 #一個文檔中每個單詞最多只能增加1 ! with open('language.txt','a',encoding='utf-8')as f: for j,k in zip(dict2.keys(),dict2.values()): f.write(j+':') f.write(str(k)) f.write('\n') def TfIdf(): dict3={} #存放語料庫中的鍵值對,生成該字典是為了進行索引 for line in open('language.txt','r+',encoding='utf-8'): (key, value) = line.strip('\n').split(':') #換行符是用strip去除的,然后通過區分冒號來區分鍵值 dict3[key] = str(value) #把對應的鍵值對存放進dict3字典中 # 根據dict3求解IDF for q in dict3.keys(): dict3[q] = math.log(3455 / (int(dict3[q]) + 1), 10) # 10是底 for j in range(1,3455): #所有文檔各自遍歷一遍 count = {} #存放每次文檔的單詞和次數 sumdict={} #用來存放TF-IDF算法后的結果 with open('txt/TF-IDF' + str(j) + '.txt', 'r', encoding='utf-8')as file: for wd in file.readlines(): #按行讀取 # 求解單詞頻率,為了TF wd=wd.replace('\n','') #去掉換行符 count[wd]=count.get(wd,0)+1 #統計在本文檔中該單詞出現的次數 for k in count.keys(): sumdict[k] = count[k] / sum(count.values()) # TF表示詞條在文檔中出現的頻率 sumdict[k]=sumdict[k]*dict3[k] #此處用sumdict存放TF-IDF值 data=[] #存儲三個最大值 with open('TF-IDF.txt', 'a', encoding='utf-8')as f: for i in range(3): data.append(max(sumdict,key=lambda x:sumdict[x])) #根據字典的值查找最大值 f.write(max(sumdict,key=sumdict.get)) #寫入文件中 f.write(' ') #用逗號來分割三個關鍵字 sumdict.pop(max(sumdict,key=sumdict.get)) #刪除最大值 f.write('\n') if __name__=='__main__': word() language() TfIdf()
from gensim.corpora import WikiCorpus import jieba import codecs from gensim.models import Word2Vec from gensim.models.word2vec import LineSentence import multiprocessing ''' 讀取中文wiki語料庫,並解析提取xml中的內容 ''' #將下載的語料轉為文本txt格式 def dataprocess(): space = " " i = 0 output = open('E:\wiki\chinawiki-articles.txt', 'w', encoding='utf-8') wiki = WikiCorpus('E:\wiki\zhwiki-latest-pages-articles.xml.bz2', lemmatize=False, dictionary={}) for text in wiki.get_texts(): output.write(space.join(text) + "\n") #分割一個詞之后換行 i = i + 1 if (i % 10000 == 0): #每一萬文章就提示一下 print('Saved ' + str(i) + ' articles') output.close() print('Finished Saved ' + str(i) + ' articles') ''' 加載停用詞表 ''' def createstoplist(stoppath): print('load stopwords...') stoplist = [line.strip() for line in codecs.open(stoppath, 'r', encoding='utf-8').readlines()] #fromkeys用於創建一個新字典,以序列seq中元素做字典的鍵,value為字典所有鍵對應的初始值 stopwords = {}.fromkeys(stoplist) #值默認為None return stopwords ''' 過濾英文 ''' def isAlpha(word): try: #isalpha() 方法檢測字符串是否只由字母組成。 return word.encode('ascii').isalpha() except UnicodeEncodeError: return False def trans_seg(): stopwords = createstoplist(r'E:\wiki\baidustop.txt') i = 0 with codecs.open('E:\wiki\seg\chinawiki-segment40.txt', 'w', 'utf-8') as wopen: print('開始...') with codecs.open('E:\wiki\zhUTF8\chinawiki-articles-jian.txt', 'r', 'utf-8') as ropen: for line in ropen.readlines(): line = line.strip() #去掉空格 i += 1 print('line ' + str(i)) #第幾行 text = '' for char in line.split(): #對每行進行列表分割 if isAlpha(char): #如果是英文就不要 continue text += char #空格加詞語 # print(text) words = jieba.cut(text) #默認模式分詞 seg = '' for word in words: if word not in stopwords: #如果在停用詞表就不用這個詞 if len(word) > 1 and isAlpha(word) == False: # 去掉長度小於1的詞和英文 if word != '\t': #空格 seg += word + ' ' wopen.write(seg + '\n') print('結束!') ''' 利用gensim中的word2vec訓練詞向量 ''' def word2vec(): print('Start...') rawdata='E:\wiki\seg\chinawiki-segment40.txt' modelpath='E:\wiki\model\chinawikimodel.model' #vectorpath='E:\word2vec\vector' model=Word2Vec(LineSentence(rawdata),size=400,window=5,min_count=5,workers=multiprocessing.cpu_count())#參數說明,gensim函數庫的Word2Vec的參數說明 model.save(modelpath) #model.wv.save_word2vec_format(vectorpath,binary=False) print("Finished!") if __name__=='__main__': # dataprocess() # trans_seg() # word2vec() model= Word2Vec.load('E:\wiki\model\chinawikimodel.model') # print(model.most_similar('開心',topn=5)) try: pro=model.similarity('開心', '不存在') except: pro=0 print(pro)
''' 計算關鍵詞與題目相似度的流程:加載題目文件與關鍵詞文件--》把題目進行分詞--》把分詞后的結果保存 --》把關鍵詞與分詞題目詞語逐一比較相似度取最大值--》每篇文章得到三個相似度(三個關鍵詞) 前期准備:jieba分詞、wiki中文語料、word2vec模型訓練、詞向量比較相似度 標題文檔:fosu1中提取,關鍵詞文檔:TF-IDF.txt中提取,皆是3454行 ''' import csv import jieba from gensim.models import Word2Vec import re #加載詞語模型,用來輸出詞語相似度 model= Word2Vec.load('E:\wiki\model\chinawikimodel.model') list1=[] #存儲分詞后的標題 list2=[] #存儲關鍵詞 list3=[] #存儲相似度 #用with同時打開兩個文件 with open('fosu1.csv','r',newline='',encoding='utf-8')as file1,open('TF-IDF.txt','r',encoding='utf-8')as file2: read1 = csv.reader(file1) # 讀取文件 title = [row[0] for row in read1] # 獲取標題 for i in title: i = jieba.cut(i, cut_all=False) #全模式識別名字的效果很差 #雖然使用精確模式有所改變,但是很多名字都不在模型中,所以沒法識別,返回錯誤 tit = ",".join(i) tit=re.compile('[\u4e00-\u9fa5]+').findall(tit) #只取中文 list1.append(tit) for j in file2.readlines(): j=j.strip() j=j.split(' ') list2.append(j) #關鍵詞 file3=open('similarity.txt','a',encoding='utf-8') n=0 #第幾個標題 for p,q in zip(list1,list2): word=" ".join(q) file3.write(title[n] + ':') file3.write(word+'|') for w in range(3): pro=[] #暫時存儲一個關鍵詞與其他標題分詞的相似度 for i in p: try: #關鍵詞與他們逐一比較相似度 pro.append(model.similarity(i,q[w])) except: #有些詞語不在模型詞典中,會報錯 if i==q[w]: #如果詞語不在模型中,但是標題中有相同的詞語,那么就把相似度設為1.0 pro.append(1.0) else: #否則為0.0 pro.append(0.0) pro=float('%.2f'%max(pro)) #取相似度最大的為關鍵詞與標題的相似度 file3.write(str(pro)+' ') file3.write('\n') n+=1 #標題+1