辨別標題黨--提取關鍵詞與比較相似度


最近好幾天都沒有更新博客,因為網絡設置崩了,然后各種扎心,最后還重裝電腦,而且還有一些軟件需要重新安裝或者配置,所以煩了好久,搞好電腦之后,老師又布置了一個任務,個人覺得很有趣--判別學校新聞是否是標題黨

雖然我不覺得老師的方法能夠很好地判別標題黨行為,但是也只能開干了!

第一步:通過爬蟲獲取學校新聞,這一部分已經在之前的文章中寫過,所以不在重復了,有點不同的是,因為從文本中提取內容列會出錯,有少數文章的內容沒有被全部提取,所以我在源代碼的基礎上改變了一下,生成了一個只存放內容的文件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

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM