在好玩的分詞(2)——分析了《三體》全集走触,我看到了這樣的三體一文中,通過分詞獲取到了三體全集文本中topn的詞及詞頻,那么本文中進一步用詞云的形式來展現(xiàn)出來。
廢話不多說补憾,直接上代碼:
#!/usr/bin/python
# coding:utf-8
# 繪制一個《三體》全集詞云
import sys
from collections import Counter
import jieba.posseg as psg
import matplotlib.pyplot as plt
from scipy.misc import imread
from wordcloud import WordCloud,ImageColorGenerator
# 對文本分詞并標注詞性,并緩存到文件
def cut_and_cache(text):
# 將文本分詞卷员,并附帶上詞性盈匾,因為數(shù)據(jù)量比較大,防止每次運行腳本都花大量時間毕骡,所以第一次分詞后就將結(jié)果存入文件cut_result.txt中
# 相當于做一個緩存削饵,格式為每個詞占一行,每一行的內(nèi)容為:
# 詞,詞性
words_with_attr = [(x.word,x.flag) for x in psg.cut(text) if len(x.word) >= 2]
print len(words_with_attr)
with open('cut_result.txt','w+') as f:
for x in words_with_attr:
f.write('{0}\t{1}\n'.format(x[0],x[1]))
return words_with_attr
# 從cut_result.txt中讀取帶詞性的分詞結(jié)果列表
def read_cut_result():
words_with_attr = []
with open('cut_result.txt','r') as f:
for x in f.readlines():
# 這里解碼成utf-8格式未巫,是為了防止后面生成詞云的時候出現(xiàn)亂碼
x = x.decode('utf-8')
pair = x.split()
if len(pair) < 2:
continue
words_with_attr.append((pair[0],pair[1]))
return words_with_attr
# 統(tǒng)計在分詞表中出現(xiàn)次數(shù)排名前topn的詞的列表窿撬,并將結(jié)果輸出到文件topn_words.txt中,每行一個詞叙凡,格式為:
# 詞,出現(xiàn)次數(shù)
def get_topn_words(words,topn):
c = Counter(words).most_common(topn)
top_words_with_freq = {}
with open('top{0}_words.txt'.format(topn),'w+') as f:
for x in c:
f.write('{0},{1}\n'.format(x[0],x[1]))
top_words_with_freq[x[0]] = x[1]
return top_words_with_freq
# 傳入文本文件的路徑file_path和topn劈伴,獲取文本文件中topn關(guān)鍵詞列表及詞頻
def get_top_words(file_path,topn):
# 讀取文本文件,然后分詞并緩存握爷,只需運行一次跛璧,后續(xù)運行腳本可注釋掉下面兩行
text = open(file_path).read()
words_with_attr = cut_and_cache(text)
# 從cut_result.txt中讀取帶詞性的分詞結(jié)果列表
words_with_attr = read_cut_result()
# 要過濾掉的詞性列表
stop_attr = ['a','ad','b','c','d','f','df','m','mq','p','r','rr','s','t','u','v','z']
# 過濾掉不需要的詞性的詞
words = [x[0] for x in words_with_attr if x[1] not in stop_attr]
# 獲取topn的詞并存入文件topn_words.txt,top_words_with_freq為一個字典新啼,在生成詞云的時候會用到赡模,格式為:
# {'aa':1002,'bb':879,'cc':456}
top_words_with_freq = get_topn_words(words = words,topn = topn)
return top_words_with_freq
# 根據(jù)傳入的背景圖片路徑和詞頻字典、字體文件师抄,生成指定名稱的詞云圖片
def generate_word_cloud(img_bg_path,top_words_with_freq,font_path,to_save_img_path,background_color = 'white'):
# 讀取背景圖形
img_bg = imread(img_bg_path)
# 創(chuàng)建詞云對象
wc = WordCloud(font_path = font_path, # 設(shè)置字體
background_color = background_color, # 詞云圖片的背景顏色漓柑,默認為白色
max_words = 500, # 最大顯示詞數(shù)為1000
mask = img_bg, # 背景圖片蒙版
max_font_size = 50, # 字體最大字號
random_state = 30, # 字體的最多模式
width = 1000, # 詞云圖片寬度
margin = 5, # 詞與詞之間的間距
height = 700) # 詞云圖片高度
# 用top_words_with_freq生成詞云內(nèi)容
wc.generate_from_frequencies(top_words_with_freq)
# 用matplotlib繪出詞云圖片顯示出來
plt.imshow(wc)
plt.axis('off')
plt.show()
# 如果背景圖片顏色比較鮮明,可以用如下兩行代碼獲取背景圖片顏色函數(shù)叨吮,然后生成和背景圖片顏色色調(diào)相似的詞云
#img_bg_colors = ImageColorGenerator(img_bg)
#plt.imshow(wc.recolor(color_func = img_bg_colors))
# 將詞云圖片保存成圖片
wc.to_file(to_save_img_path)
def main():
# 設(shè)置環(huán)境為utf-8編碼格式辆布,防止處理中文出錯
reload(sys)
sys.setdefaultencoding('utf-8')
# 獲取topn詞匯的'詞:詞頻'字典,santi.txt是當前目錄下三體全集的文本
top_words_with_freq = get_top_words('./santi.txt',300)
# 生成詞云圖片茶鉴,bg.jpg是當前目錄下的一副背景圖片锋玲,yahei.ttf是當前目錄下微軟雅黑字體文件,santi_cloud.png是要生成的詞云圖片名
generate_word_cloud('./bg.jpg',top_words_with_freq,'./yahei.ttf','./santi_cloud.png')
print 'finish'
if __name__ == '__main__':
main()
上述代碼中涵叮,bg.jpg圖片如下惭蹂,是一只豹子的剪影,像一個在黑暗森林中潛伏的獵人:
注:作為詞云背景的圖片一定要輪廓分明割粮,且圖片主體顏色要和圖片自身的背景顏色對比度較大盾碗,這樣生成的詞云圖片才能更清晰。一般剪影圖片更容易滿足這種要求舀瓢。
此外廷雅,三體全集santi.txt文本從網(wǎng)上很好搜到。
注:有個坑要注意,就是在生成詞云前要把santi.txt的編碼格式轉(zhuǎn)為utf-8格式航缀,否則可能并出不來預期的結(jié)果商架。
運行上述代碼,生成的詞云圖片如下:
最后芥玉,可以將這里的背景圖片和文本文件修改成其他的圖片和文本路徑蛇摸,那么運行上面代碼就可以馬上得到自己想要的詞云了!
代碼已經(jīng)放到:我的GitHub