1. 程式人生 > >python詞雲進階——三國版

python詞雲進階——三國版

1 實驗內容

             在進行了上一個實驗《利用Python定製個性化詞雲》之後,掌握了初步的詞雲製作。出於對三國曆史的喜愛,因此想製作一個關於《三國演義》版的詞雲,以一個新的角度去看這段歷史。但由於本人掌握的資料分析技術有限,直接處理原版的《三國演義》難度很大(因為原版中很多簡稱,例如“公”、只稱名不稱姓等),因此文字內容使用的是《白話三國》(電子趙括 著)的TXT版本(講真~找個可以分析的白話版TXT文件真的不容易)。

2 前期準備

實驗環境:python 3.6

涉及擴充套件包:re、pandas、pickle、codecs、jieba、wordcloud (這裡需要安裝jieba、wordcloud,此處採用了pip安裝)

jieba:

pip install jieba

wordcloud:

pip install wordcloud

古代很多人都有自己的“字號”,如諸葛亮,字孔明。例如在白話文中大部分稱諸葛亮,但仍有部分稱作孔明。因此需要我們找到這些對應關係,並進行替換。這裡使用的是百度知道上一個較為完整的回答,並且格式較為標準,便於處理。

問題及回答的地址:https://zhidao.baidu.com/question/192918537.html,部分資料如下,

                               

將內容複製到TXT文件中,並以utf-8格式進行儲存(因為之後的處理過程中是預設以utf-8的方式進行的)。要想進行替換,我們需要將上述資料處理為字典格式。觀察資料格式,需要做以下處理:

1、去掉多餘的空格;

2、通過split拆分資料,並作成字典格式;

3、用生成的字典替換原文中的字號,並儲存替換後的文字;

4、將姓名及詞性以字典的形式儲存(該檔案用於之後的詞雲生成)。

程式碼如下:

import re
import pandas as pd
import pickle

with open('F:/sanguo/namelist.txt','r',encoding='utf-8') as f:
    result = f.readline()  
    f.close()
    
#去掉多餘的空格    
result=re.sub(r'\s+', '', result)     

#以括號切分資料 ,把姓名和字號整理為字典格式
a=result.split(")")
del a[len(a)-1]     
dict_ming_zi=pd.DataFrame(columns=['ming','zi'])
j=0
for i in a:
    dict_ming_zi.loc[j,'ming']=str(i).split("(")[0]
    dict_ming_zi.loc[j,'zi']=str(i).split("(")[1]
    j+=1

#替換原文中的字號,並儲存替換文字
with open('F:/sanguo/三國演義白話本.txt','r',encoding='utf-8') as f1:
    original_text = f1.read()
    f1.close()
for i in range(len(dict_ming_zi)):
    original_text=original_text.replace(dict_ming_zi.iloc[i,1],dict_ming_zi.iloc[i,0])    
with open('F:/sanguo/三國演義替換文.txt','w',encoding='utf-8') as f2:    
    f2.write(original_text)
    f2.close()  

#將姓名及詞性以字典的形式儲存(該檔案用於之後的詞雲生成)
list_ming=[]
list_ming= dict_ming_zi['ming']
name_dict={}
for i in list_ming:
    name_dict[i]='nr'   
with open('F:/sanguo/dict_name.txt','wb') as f3:
    pickle.dump(name_dict,f3)
    f3.close()

通過以上操作,我們得到了三國演義替換文字.txt和dict_name.txt兩個文件。

3 詞雲的生成

關於詞雲的生成,在上一個實驗《利用Python定製個性化詞雲》中已經做出了較為詳細的介紹,此處不再贅述。此處的背景用的是三國鼎立時期的勢力劃分圖。

 

經美圖秀秀處理後的結果:

接下來是完整的詞雲生成程式碼:

import codecs
import jieba
import pickle
import numpy as np
from scipy.misc import imread
from wordcloud import WordCloud
import matplotlib.pyplot as plt


#生產詞雲文字
def seg_sentence(file_name):  
    file=open('f:/sanguo/dict_name.txt','rb')           #讀取dict_name文件,用於jieba的自定義詞典和關鍵詞的篩選      
    dict_name = pickle.load(file)
    jieba.load_userdict(dict_name)   
    with codecs.open(file_name,encoding='utf-8') as f:  #讀取文件
       original_text = f.read()                                  
    wordList = jieba.cut(original_text)                 #全文分詞,結果儲存在wordlist中
    print('---全文分詞完成---')                                      
    allow_pos = ('nr',)                                 #設定篩選引數為”nr“,名字
    tags = jieba.analyse.extract_tags(original_text, topK=1000, withWeight=False, allowPOS=allow_pos)  #從原文文字original_text中,篩選詞性為”nr“的前30個詞彙作為關鍵詞
    print('---關鍵詞篩選完成---')
    stags=" ".join(tags)                                #將關鍵詞通過空格連線為字串stags

    f2=open(u"stags.txt","w+")                          #將獲得的關鍵詞儲存到stags.txt檔案中(供除錯檢視)
    f2.write(stags)
    f2.write("\n")
    f2.close()    
                  
    count=0    
    outstr = ''                                         
    for word in wordList:                               #遍歷全文分詞結果wordlist
        if word  in stags:                              #與關鍵詞字串比較,只保留關鍵詞
            if word in dict_name:                       #在關鍵詞中只保留人名
                if len(word) > 1:                       # 去掉長度小於1的詞  
                    if word != '\t':  
                        outstr += word  
                        outstr += " " 
                        count=count+1 
    print ("---詞雲文字完成---")                                    
    return outstr                                       #將保留下的詞輸出到字串outstr中,通過空格連線為字串                     
    
# 繪製詞雲
def draw_wordcloud(file_name):
   outstr=seg_sentence(file_name)                       #呼叫分詞函式,生成只包含關鍵詞的分詞文字outstr,字串格式                            
   f2=open(u"分詞後.txt","w+")                          #將outstr儲存到 分詞後.txt檔案中 (供除錯檢視)
   f2.write(outstr)
   f2.write("\n")
   f2.close()                                           

   font='C:\Windows\Fonts\STXINGKA.TTF'                 #選擇字型路徑
   color_mask = imread("F:\sanguo\map_副本.jpg")           #讀取模板圖片,這裡使用了一張五角星圖片
                                               
   #設定詞雲引數,字型,模板,背景白色,最大詞量1000個,最大字型尺寸60
   cloud = WordCloud(font_path=font,background_color='white',mask=color_mask,max_words=1000,min_font_size=1,max_font_size=60,scale=2,height=500,width=500,relative_scaling=1)
                     
   word_cloud = cloud.generate(outstr)                  # 產生詞雲資料 word_cloud
   print ("---詞雲完成---")
   word_cloud.to_file("w_cloud.jpg")                    #詞雲儲存為圖片w_cloud.jpg
   print ("---詞雲儲存成功---")
   return word_cloud

file_name = 'F:\sanguo\三國演義替換文.txt'              #設定小說文字所在路徑

word_cloud=draw_wordcloud(file_name)                   #呼叫詞雲生成函式,生成詞雲word_cloud,並儲存成為圖片                                 
plt.figure(figsize=(20,20))
plt.imshow(word_cloud)
plt.axis("off")
plt.show()                                             #顯示詞雲圖

生成的詞雲是這樣的:

            此時詞雲引數relative_scaling設定為1,反應的是詞頻與詞大小的關聯度為1,只能說曹操的出場率很高呀,劉皇叔、諸葛亮等眾人只能算配角了。(ps.詞的位置是隨機的)

這樣可以準確的反映詞頻,詞頻高的關鍵詞字型會比較大。但是這樣的詞雲看起來並不美觀,因此我們將relative_scaling改為了0.5,此時生成的詞雲如下:

這樣看上去,比剛才好多了。

至此此次分析實驗結束,可能還有小夥伴感覺不是很美觀,這個可以根據自己的喜好調整背景圖和詞雲引數。此次是在上篇文章的基礎上完成的,因此介紹的基礎內容比較少,只是講了分析處理流程。原始碼、文件及圖片資源已經上傳,如需下載請點選:python詞雲進階——三國版

歡迎大家交流學習,QQ:285899326。