基於 jieba 和 word_cloud 生成《人民的名義》小說詞雲

基於 jieba 和 word_cloud 生成《人民的名義》小說詞雲

       由於詞雲在反映文本關鍵信息上的顯著優勢,在本文中,我選擇結合實例爲大家介紹一下 Python 中專門用來生成詞雲的一個庫——word_cloud 。
       實例中的分析對象就選擇爲最近大火的電視劇《人民的名義》小說原著,通過詞雲來分析一下小說各具魅力的人物中,究竟誰的出場率最高,誰是真正的主角。
       考慮到 Word_Cloud 的默認處理對象是英文,對中文的分詞效果不夠理想,所以在實例中還用到了一個強大的中文分詞組件——jieba ,在文章中也會給大家進行簡單介紹。

一、準備工作

1.1 word_cloud 介紹

       首先,爲大家介紹一下 word_cloud 庫的基本信息。word_cloud 是哥倫比亞大學的Andreas Müller 開發的基於 Python 的詞雲生成器,同時支持Python2 和 Python3 。 word_cloud 使用的詞雲生成算法簡潔高效,支持任意形狀的圖片模板,可以自動生成配色。也可以對詞雲中單詞的數量、配色、尺寸、排列方式等一系列參數進行自定義的設定。

       在word_cloud 庫裏,最重要的一個類是 WordCloud 。這個類中的屬性包含了詞雲生成過程中的各項相關參數,方法中則包含了文本分詞、詞雲的生成、繪製等一系列函數。首先,我們來看一下 WordCLoud 的屬性:

class wordcloud.WordCloud(font_path=None, width=400, height=200, margin=2, ranks_only=None, prefer_horizontal=0.9, mask=None, scale=1, color_func=None, max_words=200, min_font_size=4, stopwords=None, random_state=None, background_color='black', max_font_size=None, font_step=1, mode='RGB', relative_scaling=0.5, regexp=None, collocations=True, colormap=None, normalize_plurals=True)

       可以看到,WordCloud這個函數有22個參數,能夠設置詞雲生成過程中各個方面的參數,我們可以通過設定這些參數的取值來實現我們想要的效果。當然,這麼多參數,我們只需要設置我們最關心的幾個參數,其餘參數取默認值就可以了。這裏,簡單介紹一下我們將要用到的幾個重要參數:

  • 第一個參數是 font_path,字體路徑。這個參數用來選擇生成詞雲中文字使用的字體。在Linux環境中,字體默認的是DroidSansMono,如果沒有這個字體或者使用的是其他操作系統,都需要下載字體文件,對這個參數賦予字體所在路徑。需要注意的是,由於默認字體是英文字體,我們在處理中文文本時,建議使用自己選擇的漢字字體。在選擇字體的過程中,最好選擇字庫比較完整的經典字體,如黑體、宋體等字體。若使用一些字庫不夠完整的特殊字體,容易出現詞雲中一些漢字無法顯示的情況,影響效果。

  • 第二個參數是 mask ,模板圖片。這個參數用來選擇詞雲生成形狀的模板。默認不設置情況下,生成詞雲會是一個矩形。選作模板的圖片需要是一副二值圖像。模板圖像矩陣中,白色(#FF 或 #FFFFFF) 的元素位置會被排除,其餘的元素位置會被單詞填滿。也就是說,使用一副黑白圖像作爲模板時,生成的詞雲是黑色部分的形狀。輸入的模板圖片的格式支持常用格式如png、jpeg等。

  • 第三個參數是 max_words,最大單詞數。顧名思義,這個參數決定了詞雲中顯示的單詞的總數上限,我們可以根據具體應用需求來設置這個參數的大小。類似的還有max_font_size(最大字體尺寸)、min_font_size(最小字體尺寸)、backgroud_color(背景顏色)等一系列功能明確的參數,可以根據需要自由設置,沒有特殊的限制。

       關於 WordCloud 類的屬性,以上的介紹已經可以滿足我們的基本使用需要,接下來我們來了解一下 WordCloud 類中的主要方法。WordCloud 類中包含的方法如下所示:

方法 簡介
fit_words(frequencies) Create a word_cloud from words and frequencies
generate(text) Generate wordcloud from text
generate_from_frequencies(frequencies[, …]) Create a word_cloud from words and frequencies
generate_from_text(text) Generate wordcloud from text
process_text(text) Splits a long text into words, eliminates the stopwords
recolor([random_state, color_func, colormap]) Recolor existing layout
to_array() Convert to numpy array
to_file(filename) Export to image file
to_html() Export to html file
to_image() Export to image

       在這些方法函數中,本篇將會用到的函數主要是從文本中生成詞雲的函數 generate(text) 。函數的輸入是txt格式的文本文件,輸出最終的詞雲數據。這裏需要注意的是,函數輸入的文本文件對內容格式是有要求的。文本必須由一個個獨立分隔開的詞語構成,這樣函數纔可以對每個詞語的出現頻率進行統計,生成詞雲。

       在本篇的實例中,我們處理的對象是《人民的名義》小說文本,文本全部由句子構成,不能直接作爲 generate 函數的輸入值。因此,我們需要對由句子構成的文本進行”分詞“的預處理。顧名思義,分詞就是將句子分解成若干個獨立的詞彙。在上表中可以看到,WordCloud 類中提供了實現分詞功能的函數 process_text(text)。但是這個函數的設計是主要面向英文文本的分詞的,所以對中文的分詞效果不能令人滿意。

       爲了解決分詞的問題,本篇選擇了中文分詞工具庫 jieba,下面就介紹一下jieba 相關的基本知識。

1.2 Jieba 介紹

       Jieba,也就是“結巴”中文分詞,是一個非常強大且完善的中文分詞組件。Jieba 庫有很多語言的實現版本, Python 版本同時支持 Python2 和 Python3。

       Jieba的主要功能特性有以下幾點:

  • 支持三種分詞模式:

    • 精確模式,試圖將句子最精確地切開,適合文本分析;
    • 全模式,把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義;
    • 搜索引擎模式,在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜索引擎分詞。
  • 支持繁體分詞

  • 支持自定義詞典
  • MIT 授權協議

       Jieba能夠實現分詞、添加自定義詞典、關鍵詞提取、詞性標註、並行分詞、Tokenize返回詞語在原文的起止位置、ChineseAnalyzer for Whoosh 搜索引擎、命令行分詞等一系列非常豐富功能。在本篇當中,我們主要會用到分詞、添加自定義詞典和關鍵詞提取的功能,下面分別介紹一下這三個功能的基本實現。

1.2.1 分詞功能
  • jieba.cut 方法接受三個輸入參數: 需要分詞的字符串;cut_all 參數用來控制是否採用全模式;HMM 參數用來控制是否使用 HMM 模型
  • jieba.cut_for_search 方法接受兩個參數:需要分詞的字符串;是否使用 HMM 模型。該方法適合用於搜索引擎構建倒排索引的分詞,粒度比較細
  • 待分詞的字符串可以是 unicode 或 UTF-8 字符串、GBK 字符串。注意:不建議直接輸入 GBK 字符串,可能無法預料地錯誤解碼成 UTF-8
  • jieba.cut 以及 jieba.cut_for_search 返回的結構都是一個可迭代的 generator,可以使用 for 循環來獲得分詞後得到的每一個詞語(unicode),或者用jieba.lcut 以及 jieba.lcut_for_search 直接返回 list
  • jieba.Tokenizer(dictionary=DEFAULT_DICT) 新建自定義分詞器,可用於同時使用不同詞典。jieba.dt 爲默認分詞器,所有全局分詞相關函數都是該分詞器的映射。

代碼示例

# encoding=utf-8
import jieba

seg_list = jieba.cut("我來到北京清華大學", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式

seg_list = jieba.cut("我來到北京清華大學", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精確模式

seg_list = jieba.cut("他來到了網易杭研大廈")  # 默認是精確模式
print(", ".join(seg_list))

seg_list = jieba.cut_for_search("小明碩士畢業於中國科學院計算所,後在日本京都大學深造")  # 搜索引擎模式
print(", ".join(seg_list))
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
Loading model cost 1.059 seconds.
Prefix dict has been built succesfully.


Full Mode: 我/ 來到/ 北京/ 清華/ 清華大學/ 華大/ 大學
Default Mode: 我/ 來到/ 北京/ 清華大學
他, 來到, 了, 網易, 杭研, 大廈
小明, 碩士, 畢業, 於, 中國, 科學, 學院, 科學院, 中國科學院, 計算, 計算所, ,, 後, 在, 日本, 京都, 大學, 日本京都大學, 深造

1.2.2 添加自定義詞典功能

  • 開發者可以指定自己自定義的詞典,以便包含 jieba 詞庫裏沒有的詞。雖然 jieba 有新詞識別能力,但是自行添加新詞可以保證更高的正確率
  • 用法: jieba.load_userdict(file_name) # file_name 爲文件類對象或自定義詞典的路徑
  • 詞典格式和 dict.txt 一樣,一個詞佔一行;每一行分三部分:詞語、詞頻(可省略)、詞性(可省略),用空格隔開,順序不可顛倒。file_name 若爲路徑或二進制方式打開的文件,則文件必須爲 UTF-8 編碼。
  • 詞頻省略時使用自動計算的能保證分出該詞的詞頻。
1.3.3 關鍵詞提取功能

基於 TF-IDF 算法的關鍵詞抽取

import jieba.analyse

  • jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
  • sentence 爲待提取的文本
  • topK 爲返回幾個 TF/IDF 權重最大的關鍵詞,默認值爲 20
  • withWeight 爲是否一併返回關鍵詞權重值,默認值爲 False
  • allowPOS 僅包括指定詞性的詞,默認值爲空,即不篩選
  • jieba.analyse.TFIDF(idf_path=None) 新建 TFIDF 實例,idf_path 爲 IDF 頻率文件

基於 TextRank 算法的關鍵詞抽取

  • jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=(‘ns’, ‘n’, ‘vn’, ‘v’)) 直接使用,接口相同,注意默認過濾詞性。
  • jieba.analyse.TextRank() 新建自定義 TextRank 實例

1.3 環境搭建

       在對 word_cloud 和 jieba 兩個庫有了基本的瞭解之後,我們來學習一下兩個庫的安裝和相關環境的搭建。

1.3.1 word_cloud 的安裝
1.3.2 jieba 的安裝
  • 全自動安裝:easy_install jieba 或者 pip install jieba / pip3 install jieba
    • 半自動安裝:先下載 http://pypi.python.org/pypi/jieba/ ,解壓後運行 python setup.py install
    • 手動安裝:將 jieba 目錄放置於當前目錄或者 site-packages 目錄
    • 通過 import jieba 來引用
1.3.3 Anaconda 的使用

       個人在這裏推薦使用 Anaconda 來配置 Python 開發環境。
Anaconda是專注於數據分析的Python發行版本,包含了conda、Python等190多個科學包及其依賴項。而conda 是開源包(packages)和虛擬環境(environment)的管理系統。

  • packages 管理: 可以使用 conda 來安裝、更新 、卸載工具包 ,並且它更關注於數據科學相關的工具包。在安裝 anaconda 時就預先集成了像 Numpy、Scipy、 pandas、Scikit-learn 這些在數據分析中常用的包。另外值得一提的是,conda 並不僅僅管理Python的工具包,它也能安裝非python的包。比如在新版的 Anaconda 中就可以安裝R語言的集成開發環境 Rstudio。
  • 虛擬環境管理: 在conda中可以建立多個虛擬環境,用於隔離不同項目所需的不同版本的工具包,以防止版本上的衝突。對糾結於 Python 版本的同學們,我們也可以建立 Python2 和 Python3 兩個環境,來分別運行不同版本的 Python 代碼。

       Anaconda通過管理工具包、開發環境、Python版本,大大簡化了工作流程。不僅可以方便地安裝、更新、卸載工具包,而且安裝時能自動安裝相應的依賴包,同時還能使用不同的虛擬環境隔離不同要求的項目。

       如果想要安裝Anaconda的話,可以通過官網下載頁面下載 Anaconda 的安裝程序以及查看安裝說明,在這裏就不再贅述了。

1.4 實現思路

       在完成基礎知識瞭解和環境配置後,我們可以來思考一下具體的實現過程了。


       我們的目標是生成《人民的名義》小說詞雲,我們希望詞雲中的詞彙只有角色的名字,沒有其他無關詞彙,這樣才能更好地反映出角色的比重。


       我們的處理對象是從網絡獲得的《人民的名義》小說 txt 文件,編碼格式爲 utf-8 ,字符數爲268375。


       根據之前的基礎知識,我們不難獲得整個程序的實現思路:

  1. 分詞
    • 小說文本整體分詞
    • 構建自定義人名詞典
    • 篩選關鍵詞
  2. 生成詞雲,繪製圖片

       因此,我們只需要設計兩個函數。第一個函數是分詞函數,用來實現小說的整體分詞和人名篩選等功能,獲得只包含人名的分詞結果。第二個函數就是詞雲生成函數,使用分詞函數的分詞結果作爲輸入,對詞雲的模板、詞量等參數進行設置,輸出最終的詞雲結果,並保存爲圖片文件。

二、程序設計

2.1 庫的導入

       首先,程序的開始我們要聲明編碼方式,並導入需要用到的庫文件,代碼如下:

#-*- coding:utf-8 -*-
#encoding=utf8
import codecs
import jieba
jieba.load_userdict("namedict.txt")
import jieba.analyse as analyse
from wordcloud import WordCloud
from scipy.misc import imread
from os import path

       可以看到,我們引入了 codecs,是爲了使用 codecs.open() 函數打開文本文件,引用了jieba.analyse 是爲了調用其中的 extract_tags 函數來實現關鍵詞的篩選。值得注意的是,在這裏,我加載了自定義字典文件 “namedict.txt”。在這個字典文件中,依照溫暖的文檔要求的格式,記錄了21個小說中人物角色的姓名,並標註詞性爲”nr“,代表名字。下面是部分示例。

侯亮平 nr

沙瑞金 nr

祁同偉 nr

李達康 nr

高育良 nr

       通過這個自定義詞典的加載,我們可以保證分詞過程中,角色名字可以正確完整地被分割出來,並且可以根據詞性”nr“,將所有名字篩選出來。

2.2 分詞函數的實現

代碼如下,代碼的原理在註釋中有詳細介紹:

def seg_sentence(file_name):  
    with codecs.open(file_name,encoding='utf-8') as f:     #打開文件
       original_text = f.read()                   #讀取文件內容爲字符original_text
    wordList = jieba.cut(original_text)          #全文分詞,結果存儲在wordlist中
    print('全文分詞完成...')
    allow_pos = ('nr',)                           #設置篩選參數爲”nr“,名字
    tags = jieba.analyse.extract_tags(original_text, topK=30, withWeight=False, allowPOS=allow_pos)
                       #從原文文本original_text中,篩選詞性爲”nr“的前30個詞彙作爲關鍵詞
    print('關鍵詞篩選完成...')
    stags=" ".join(tags)                          #將關鍵詞通過空格連接爲字符串stags

    f2=open(u"stags.txt","w+")
    f2.write(stags)
    f2.write("\n")
    f2.close()                      #將獲得的關鍵詞存儲到stags.txt文件中(供調試查看)

    outstr = ''                                         
    for word in wordList:                             #遍歷全文分詞結果wordlist
        if word  in stags:                          #與關鍵詞字符串比較,只保留關鍵詞
            if len(word) > 1:                       # 去掉長度小於1的詞  
                if word != '\t':  
                    outstr += word  
                    outstr += " "                
                                  #將保留下的詞輸出到字符串outstr中,通過空格連接爲字符串
    return outstr  
    print ("生產詞雲文本...")

2.3 詞雲生成函數的實現

代碼如下,代碼的原理在註釋中有詳細介紹:

# 繪製詞雲
def draw_wordcloud(file_name):

   outstr=seg_sentence(file_name)                                   
                               #調用分詞函數,生成只包含關鍵詞的分詞文本outstr,字符串格式

   f2=open(u"分詞後.txt","w+")
   f2.write(outstr)
   f2.write("\n")
   f2.close()                          #將outstr保存到 分詞後.txt文件中 (供調試查看)

   font='/home/xplanet/下載/black.ttf'                       
                                                       #選擇字體路徑,這裏使用了黑體
   color_mask = imread("/home/xplanet/下載/star.jpeg")  
                                               #讀取模板圖片,這裏使用了一張五角星圖片
   cloud = WordCloud(font_path=font,background_color='white',mask=color_mask,max_words=100,max_font_size=60)
                        #設置詞雲參數,字體,模板,背景白色,最大詞量100個,最大字體尺寸60
   word_cloud = cloud.generate(outstr)                  # 產生詞雲數據 word_cloud


   print ("詞雲完成...")
   word_cloud.to_file("w_cloud.jpg")                    #詞雲保存爲圖片w_cloud.jpg
   print ("詞雲保存成功...")
   return word_cloud

2.4 函數的調用

       兩個主要函數定義完成後,就可以設置小說文本路徑,直接調用詞雲生成函數生成詞雲了。

       這裏需要的代碼也很簡單,如下所示:

file_name = '/home/xplanet/下載/人民的名義2.txt'         #設置小說所在路徑
word_cloud=draw_wordcloud(file_name)                   
                                  #調用詞雲生成函數,生成詞雲word_cloud,並保存成爲圖片

import matplotlib.pyplot as plt
plt.imshow(word_cloud)
plt.axis("off")
plt.show()                                      #引入matplotlib模塊是爲了顯示詞雲圖

三、實踐結果

將上述代碼編寫到一個Python文件txtwc.py中,如下所示:

# -*- coding:utf-8 -*-
#encoding=utf8

import codecs
import jieba
jieba.load_userdict("namedict.txt")
import jieba.analyse as analyse
from wordcloud import WordCloud
from scipy.misc import imread
from os import path

def seg_sentence(file_name):  
    with codecs.open(file_name,encoding='utf-8') as f:     #打開文件
       original_text = f.read()                   #讀取文件內容爲字符串original_text
    wordList = jieba.cut(original_text)             #全文分詞,結果存儲在wordlist中
    print('全文分詞完成...')
    allow_pos = ('nr',)                                  #設置篩選參數爲”nr“,名字
    tags = jieba.analyse.extract_tags(original_text, topK=30, withWeight=False, allowPOS=allow_pos)
                        #從原文文本original_text中,篩選詞性爲”nr“的前30個詞彙作爲關鍵詞
    print('關鍵詞篩選完成...')
    stags=" ".join(tags)                         #將關鍵詞通過空格連接爲字符串stags

    f2=open(u"stags.txt","w+")
    f2.write(stags)
    f2.write("\n")
    f2.close()                      #將獲得的關鍵詞存儲到stags.txt文件中(供調試查看)

    outstr = ''                                         
    for word in wordList:                               #遍歷全文分詞結果wordlist
        if word  in stags:                          #與關鍵詞字符串比較,只保留關鍵詞
            if len(word) > 1:                               # 去掉長度小於1的詞  
                if word != '\t':  
                    outstr += word  
                    outstr += " "                
                                  #將保留下的詞輸出到字符串outstr中,通過空格連接爲字符串
    return outstr  
    print ("生產詞雲文本...")

# 繪製詞雲
def draw_wordcloud(file_name):

   outstr=seg_sentence(file_name)    
                               #調用分詞函數,生成只包含關鍵詞的分詞文本outstr,字符串格式

   f2=open(u"分詞後.txt","w+")
   f2.write(outstr)
   f2.write("\n")
   f2.close()                    #將outstr保存到 分詞後.txt文件中 (供調試查看)

   font='/home/xplanet/下載/black.ttf'                  #選擇字體路徑,這裏使用了黑體
   color_mask = imread("/home/xplanet/下載/star.jpeg")  
                                               #讀取模板圖片,這裏使用了一張五角星圖片
   cloud = WordCloud(font_path=font,background_color='white',mask=color_mask,max_words=100,max_font_size=60)
                      #設置詞雲參數,字體,模板,背景白色,最大詞量100個,最大字體尺寸60
   word_cloud = cloud.generate(outstr)                # 產生詞雲數據 word_cloud


   print ("詞雲完成...")
   word_cloud.to_file("w_cloud.jpg")                                           #詞雲保存爲圖片w_cloud.jpg
   print ("詞雲保存成功...")
   return word_cloud

file_name = '/home/xplanet/下載/人民的名義2.txt'         #設置小說所在路徑
word_cloud=draw_wordcloud(file_name)                   
                                   #調用詞雲生成函數,生成詞雲word_cloud,並保存成爲圖片

import matplotlib.pyplot as plt
plt.imshow(word_cloud)
plt.axis("off")
plt.show()                                       #引入matplotlib模塊是爲了顯示詞雲圖

運行文件,得到結果如下圖所示:


       從結果圖可以看出,在衆多魅力各異的角色中,侯亮平和李達康是《人民的名義》中登場率最高的人物,祁同偉、高育良等人的存在感也不相上下。看來,達康書記在網絡上的超高人氣不是空穴來風啊!

發佈了30 篇原創文章 · 獲贊 63 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章