一、實驗介紹
1.1 實驗內容
在互聯網時代,人們獲取信息的途徑多種多樣,大量的信息涌入到人們的視線中。如何從浩如煙海的信息中提煉出關鍵信息,濾除垃圾信息,一直是現代人關注的問題。在這個信息爆炸的時代,我們每時每刻都要更新自己的知識儲備,而網絡是最好的學習平台。對信息過濾和處理能力強,學習效率就會得到提高。“詞雲”就是為此而誕生的。“詞雲”是對網絡文本中出現頻率較高的“關鍵詞”予以視覺上的突出,形成“關鍵詞雲層”或“關鍵詞渲染”,從而過濾掉大量的無意義信息,使瀏覽者只要一眼掃過詞雲圖片就可以領略文章或者網頁內容的主旨。不僅如此,一幅制作精美的詞雲圖片,可以起到一圖勝千言的效果,在報告或者PPT
中適當的使用詞雲,會使表達更清晰充分,為演講者表達的意義加分。本實驗將使用Python
的wordcloud
擴展包制作詞雲,生成圖片保存。並介紹如何改進wordcloud
擴展包使其能顯示中文字符,最后介紹如何使用自己喜歡的圖片定制詞雲圖片輪廓。
1.2 實驗知識點
- 制作詞雲的基本步驟和原理
Python
代碼實現詞雲制作wordcloud
擴展包的使用- 使用自定義圖片制作詞雲,分析《三體》I、 II、 III的關鍵詞
1.3 實驗環境
該實驗在ubuntu14.04
下完成,由於Python
具有跨平台特性,該實驗的代碼也可以運行於Windows
和Mac
系統上,只需要對字體部分做相應處理即可。
python2.7
Xfce
終端
1.4 適合人群
本課程難度為一般,屬於初級級別課程,適合具有Python
基礎的用戶,熟悉python
基礎知識加深鞏固。
1.5 代碼獲取
你可以通過下面命令將代碼下載到實驗樓環境中,作為參照對比進行學習。
$ wget http://labfile.oss.aliyuncs.com/courses/756/simple.py
$ wget http://labfile.oss.aliyuncs.com/courses/756/my_word_cloud.py
二、實驗原理
詞雲的原理是對輸入的文本數據進行詞頻統計,根據詞匯出現頻率的不同,按不同比例顯示出詞匯,生成圖片。頻率高的詞匯顯示的大,頻率低的詞匯顯示的小。文本數據可以是本地數據,也可是是爬蟲動態從網絡中獲取的。
三、開發准備
打開Xfce
終端,進入 Code
目錄,創建 work
文件夾, 將其作為課程的工作目錄。下載並安裝實驗需要的擴展包 。如果大家平時想在自己的電腦上進行實驗,無論是Windows
還是Linux
還是Mac
,都強烈推薦安裝Anaconda
,這是一個Python
的科學計算包,里面幾乎包含了常用的所有擴展包,不用自己費力安裝了,該軟件由Python
之父帶頭維護,三個平台同時更新。
$ mkdir work && cd work $ sudo apt-get update $ sudo apt-get install python-dev $ sudo pip install numpy $ sudo apt-get install python-matplotlib $ sudo apt-get install python-pil
下載小說《三體》I、 II、 III。
$ wget http://labfile.oss.aliyuncs.com/courses/756/santi.txt
$ wget http://labfile.oss.aliyuncs.com/courses/756/santi2.txt
$ wget http://labfile.oss.aliyuncs.com/courses/756/santi3.txt
安裝wordcloud
擴展包。
$ sudo pip install wordcloud
四、實驗步驟
5.1 運行一個簡單工程,測試擴展包安裝是否正常
在對《三體》進行處理之前,我們先運行一下官方的示例程序,確保擴展包安裝正常,程序能夠正常工作。在work
目錄下新建python
腳本,命名為simple.py
,
$ gedit simple.py
代碼如下:
#!/usr/bin/env python """ Minimal Example =============== Generating a square wordcloud from the US constitution using default arguments. """ from os import path from wordcloud import WordCloud d = path.dirname(__file__) # Read the whole text. text = open(path.join(d, 'constitution.txt')).read() # Generate a word cloud image wordcloud = WordCloud().generate(text) # Display the generated image: # the matplotlib way: import matplotlib.pyplot as plt plt.imshow(wordcloud) plt.axis("off") # lower max_font_size wordcloud = WordCloud(max_font_size=40).generate(text) plt.figure() plt.imshow(wordcloud) plt.axis("off") plt.show()
由代碼可見,程序運行時會搜尋腳本所在的路徑下的文本文件“constitution.txt”
,所以我們在運行腳本前需要將這個文本放入work
文件夾下面。 通過下面的命令下載文本:
$ wget http://labfile.oss.aliyuncs.com/courses/756/constitution.txt
在work
文件夾下啟動控制台,操作如下圖所示:
在控制台中運行腳本:
$ python simple.py
如果擴展包安裝一切正常,程序將輸出如下窗口:
至此,我們得到了一個英文詞雲。
5.2 解決中文顯示問題
我們已經成功安裝了wordcloud
擴展包,並成功運行了一個示例文件。但是這個示例文件有很多問題,首先,顯示的是英文字符,在面對中國同事或者老板做報告和分享時,使用英文的詞雲明顯不合適,而且很多文本本身就是中文詞匯,沒法制作成英文詞雲;詞雲的外輪廓顯示的方方正正中規中矩,比較呆板,沒有美感。以上問題,我們一一來解決。首先,我們先解決中文顯示的問題。 我們先嘗試一下,如果什么都不做,直接把一本小說輸入到simple.py
文件中,看看輸出結果是什么樣子的。我們只需要修改源文件成為下面這樣,注意在文件頭部要聲明文件用utf8
編碼:
#!/usr/bin/env python #-*- coding: utf-8 -*- """ Minimal Example =============== Generating a square wordcloud from the US constitution using default arguments. """ from os import path from wordcloud import WordCloud d = path.dirname(__file__) # Read the whole text. #text = open(path.join(d, 'constitution.txt')).read() text = open(u"santi.txt").read() # Generate a word cloud image wordcloud = WordCloud().generate(text) # Display the generated image: # the matplotlib way: import matplotlib.pyplot as plt plt.imshow(wordcloud) plt.axis("off") # lower max_font_size wordcloud = WordCloud(max_font_size=40).generate(text) plt.figure() plt.imshow(wordcloud) plt.axis("off") plt.show()
在控制台中運行程序,得到的結果是這樣的:
是不是激動地以為自己成功了?仔細看看這個詞雲,一本中文小說,統計出來的最高詞匯居然是3K
和CPU
?這可不是計算機雜志啊!所以這個結果肯定是有問題的,之少我們要知道這本小說畫出來的詞雲應該是漢字才對。
出現上面詭異的結果有兩個,第一是三體這本小說的編碼不是utf8
的,小說里的漢字是使用gbk
編碼的。所以我們直接使用
text = open(u"santi.txt").read()
這句程序去讀取文件的時候,除了英文單詞,其他的讀出來都是亂碼,wordcloud
不認識這些亂碼,自然就不能顯示其頻率了。 好的那我們現在來修改一下代碼,機智的你肯定知道怎么修改了,對,改成下面這個樣子:
text = open(u"santi.txt").read().decode('gbk')
再看看這次的輸出變成了什么,我們大膽猜一下,這次肯定不會是英文最大了。對的,這次的輸出是這個樣子的:
這怎么回事呢? 仔細看發現一個英文都沒有了,說明我們正確識別了漢字。那么這些框框出現的頻率比英文高,他們肯定是漢字啊!但是漢字怎么顯示成這樣了呢?這是因為wordcloud
沒有找到用於顯示漢字的字體啊! 我們都知道Ubuntu
是外國人搞出來的系統,所以對中文的支持肯定沒有對英文那么好,尤其是字體什么的,更少了。而wordcloud
也是個外國人開發的詞雲庫,這倆貨都沒考慮到顯示中文的問題。 但是呢,既然python
能顯示中文,那么wordcloud
就應該也可以的。我們來想想辦法解決這個問題。 仔細的看一下我們的代碼,我們發現,生成詞雲的關鍵環節是這一句:
wordcloud = WordCloud(max_font_size=40).generate(text)
我們仔細看看這個類,傳給它的參數里有個關鍵參數:
font_path : string
Font path to the font that will be used (OTF or TTF). Defaults to DroidSansMono path on a Linux machine. If you are on another OS or don't have this font, you need to adjust this path.
恩,我們發現可以指定一個字體文件給它,代替默認的字體顯示詞雲。問題轉化為我們要找一個linux
下支持漢字的字體文件。我這邊隨手找了一個ubuntu
系統中安裝的字體DroidSansFallbackFull.ttf
,為了防止在別的linux
系統中沒有這個字體而帶來麻煩,干脆直接把字體文件放在work
文件夾下讓它跟着源文件走,這樣就不會出現找不到的情況啦。 通過下面的命令下載字體文件:
$ wget http://labfile.oss.aliyuncs.com/courses/756/DroidSansFallbackFull.ttf
將字體文件放在python
腳本所在的文件夾下,然后修改源代碼,首先找到我們自己的字體文件:
font=os.path.join(os.path.dirname(__file__), "DroidSansFallbackFull.ttf")
然后在我們的源程序中,實例化wordcloud
類的兩個地方,指定wordcloud
使用我們自己的字體文件:
wordcloud = WordCloud(font_path=font).generate(text)
wordcloud = WordCloud(font_path=font,max_font_size=40).generate(text)
好的,修改完以后我們再看一下執行效果:
OK,我們期望的目的達到了!
5.3 定制詞雲
我們經常在網上看到別人家的詞雲都是奇形怪狀的,像下面這樣:
所以看着我們自己方方正正的詞雲,是不是感覺太中規中矩了?都不好意思拿出手了吧? 沒關系,我們也可以做一個不規則邊緣的詞雲! 為了達到一個定制詞雲的效果,我們需要一個圖片作為mask
,這個mask
的作用就是為我們的詞雲提供一個空間,讓我們的詞雲只在這個空間里顯示,這就達到了類似上面詞雲的效果。 我們的mask
圖片是星球大戰的士兵的頭盔,長成這個樣子:
做實驗時請在這里下載:
$ wget http://labfile.oss.aliyuncs.com/courses/756/stormtrooper_mask.png
為此,我們需要修改我們的代碼,增加圖片mask
,修改后的代碼如下:
#!/usr/bin/python #-*- coding: utf-8 -*- """ Using custom colors ==================== Using the recolor method and custom coloring functions. """ import numpy as np from PIL import Image from os import path import matplotlib.pyplot as plt import random import os from wordcloud import WordCloud, STOPWORDS font=os.path.join(os.path.dirname(__file__), "DroidSansFallbackFull.ttf") def grey_color_func(word, font_size, position, orientation, random_state=None, **kwargs): return "hsl(0, 0%%, %d%%)" % random.randint(60, 100) d = path.dirname(__file__) mask = np.array(Image.open(path.join(d, "stormtrooper_mask.png"))) text = open(u"santi.txt").read().decode('gbk') # preprocessing the text a little bit text = text.replace(u"程心說", u"程心") text = text.replace(u"程心和", u"程心") text = text.replace(u"程心問", u"程心") # adding movie script specific stopwords stopwords = set(STOPWORDS) stopwords.add("int") stopwords.add("ext") wc = WordCloud(font_path=font,max_words=2000, mask=mask, stopwords=stopwords, margin=10, random_state=1).generate(text) # store default colored image default_colors = wc.to_array() plt.title("Custom colors") plt.imshow(wc.recolor(color_func=grey_color_func, random_state=3)) wc.to_file("a_new_hope.png") plt.axis("off") plt.figure() plt.title(u"三體-詞頻統計") plt.imshow(default_colors) plt.axis("off") plt.show()
這段代碼對詞雲的顯示結果做了一點點修改,例如,“程心說”應該算是“程心”的詞頻,而不應該獨立計算,所以程序中做了一個簡單的替換。在試驗環境中不一定能輸入漢字,所以大家運行這個代碼體驗一下,以后在自己的電腦上安裝中文輸入法即可修改漢字了。 這段代碼的運行結果如下:
我們使用了星球大戰的武士的頭盔作為詞雲形狀,怎么樣,看起來還不錯吧?
然而,我們的任務並沒有結束。我們說了要自己定制詞雲,那么就連這個mask圖片也好根據我們自己的喜好進行定制。 為了在ubuntu
下將我們喜歡的圖片作為mask
圖片,我們需要安裝gimp
軟件:
$ sudo apt-get install gimp
然后我隨意上網百度了一個美女圖片,就是這面這張:
請使用下面命令獲取該美女圖片的jpg
格式:
$ wget http://labfile.oss.aliyuncs.com/courses/756/04.jpg
圖片有什么要求呢?恩,最好是背景是純色的,這樣好處理,當然如果有PS
高手幫忙的話,背景是什么也無所謂了。我們用gimp
軟件對這幅圖片進行處理,把除了女孩之外的背景改為白色,就可以作為mask圖片使用了。好下面我們動手開始制作。 首先,在圖層頁面下,右鍵這張圖,增加alpha
圖層:
然后,使用左側工具欄中的魔術棒工具,在這個姑娘身上隨便畫一下,就選中了這個姑娘:
然后,在空白區域,右鍵,編輯,使用白色作為背景顏色填充圖片:
搞定之后,我們把圖片導出來:
注意導出的時候選擇png
格式,如下設置:
然后我們就得到了這個mask圖片。我將其重命名為04.png
我們修改代碼使用這個圖片作為mask
圖片:
mask = np.array(Image.open(path.join(d, "04.png")))
請使用如下命令獲取圖片04.png
:
$ wget http://labfile.oss.aliyuncs.com/courses/756/04.png
再看我們的運行結果:
好的,至此我們就得到了定制的詞雲。
五、實驗總結
我們使用wordcloud
擴展包實現了定制詞雲,通過指定字體文件解決了wordcloud
默認不能顯示中文的問題,進一步,使用gimp
軟件實現了自定義mask
圖片的功能。最后,使用自定義的詞雲分析了小說《三體》的詞頻,制作了詞雲。