基於微博數據用 Python 打造一顆「心」
一年一度的西方情人節過去了,朋友圈各種曬,曬自拍,曬娃,曬美食,秀恩愛的。程序員在曬什麼,程序員在加班。但是禮物還是少不了的,送什麼好?作為程序員,我準備了一份特別的禮物,基於以往發的微博數據用 Python 打造一顆「心」,我想她一定會感動得哭了吧。哈哈
準備工作
有了想法之後就開始行動了,自然最先想到的就是用 Python 了,大體思路就是把微博數據爬下來,數據經過清洗加工後再進行分詞處理,處理後的數據交給詞雲工具,配合科學計算工具和繪圖工具製作成圖像出來,涉及到的工具包有:
requests 用於網路請求爬取微博數據,結巴分詞進行中文分詞處理,詞雲處理庫 wordcloud,圖片處理庫 Pillow,科學計算工具 NumPy ,類似於 MATLAB 的 2D 繪圖庫 Matplotlib
工具安裝
安裝這些工具包時,不同系統平台有可能出現不一樣的錯誤,wordcloud,requests,jieba 都可以通過普通的 pip 方式在線安裝,
pip install wordcloudnpip install requestsnpip install jieban
在Windows 平台安裝 Pillow,NumPy,Matplotlib 直接用 pip 在線安裝會出現各種問題,推薦的一種方式是在一個叫 Python Extension Packages for Windows 的第三方平台下載 相應的 .whl 文件安裝。可以根據自己的系統環境選擇下載安裝 cp27 對應 python2.7,amd64 對應 64 位系統。下載到本地後進行安裝
pip install Pillow-4.0.0-cp27-cp27m-win_amd64.whlnpip install scipy-0.18.0-cp27-cp27m-win_amd64.whlnpip install numpy-1.11.3+mkl-cp27-cp27m-win_amd64.whlnpip install matplotlib-1.5.3-cp27-cp27m-win_amd64.whln
其他平台可根據錯誤提示 Google 解決。或者直接基於 Anaconda 開發,它是 Python 的一個分支,內置了大量科學計算、機器學習的模塊 。
獲取數據
新浪微博官方提供的 API 是個渣渣,只能獲取用戶最新發布的5條數據,退而求其次,使用爬蟲去抓取數據,抓取前先評估難度,看看是否有人寫好了,在GitHub逛了一圈,基本沒有滿足需求的。倒是給我提供了一些思路,於是決定自己寫爬蟲。使用 歡迎登錄 - 新浪微博 移動端網址去爬取數據。發現介面 http://m.weibo.cn/index/my?format=cards&page=1 可以分頁獲取微博數據,而且返回的數據是 json 格式,這樣就省事很多了,不過該介面需要登錄後的 cookies 信息,登錄自己的帳號就可以通過 Chrome 瀏覽器 找到 Cookies 信息。
實現代碼:
def fetch_weibo():n api = "http://m.weibo.cn/index/my?format=cards&page=%s"n for i in range(1, 102):n response = requests.get(url=api % i, cookies=cookies)n data = response.json()[0]n groups = data.get("card_group") or []n for group in groups:n text = group.get("mblog").get("text")n text = text.encode("utf-8")n text = cleanring(text).strip()n yield textn
查看微博的總頁數是101,考慮到一次性返回一個列表對象太費內存,函數用 yield 返回一個生成器,此外還要對文本進行數據清洗,例如去除標點符號,HTML 標籤,「轉發微博」這樣的字樣。
保存數據
數據獲取之後,我們要把它離線保存起來,方便下次重複使用,避免重複地去爬取。使用 csv 格式保存到 weibo.csv 文件中,以便下一步使用。數據保存到 csv 文件中打開的時候可能為亂碼,沒關係,用 notepad++查看不是亂碼。
def write_csv(texts):n with codecs.open(weibo.csv, w) as f:n writer = csv.DictWriter(f, fieldnames=["text"])n writer.writeheader()n for text in texts:n writer.writerow({"text": text})nndef read_csv():n with codecs.open(weibo.csv, r) as f:n reader = csv.DictReader(f)n for row in reader:n yield row[text]n
分詞處理
從 weibo.csv 文件中讀出來的每一條微博進行分詞處理後再交給 wordcloud 生成詞雲。結巴分詞適用於大部分中文使用場景,使用停止詞庫 stopwords.txt 把無用的信息(比如:的,那麼,因為等)過濾掉。
def word_segment(texts):n jieba.analyse.set_stop_words("stopwords.txt")n for text in texts:n tags = jieba.analyse.extract_tags(text, topK=20)n yield " ".join(tags)n
生成圖片
數據分詞處理後,就可以給 wordcloud 處理了,wordcloud 根據數據裡面的各個詞出現的頻率、權重按比列顯示關鍵字的字體大小。生成方形的圖像,如圖:
是的,生成的圖片毫無美感,畢竟是要送人的也要拿得出手才好炫耀對吧,那麼我們找一張富有藝術感的圖片作為模版,臨摹出一張漂亮的圖出來。我在網上搜到一張「心」型圖:
生成圖片代碼:
def generate_img(texts):n data = " ".join(text for text in texts)n mask_img = imread(./heart-mask.jpg, flatten=True)n wordcloud = WordCloud(n font_path=msyh.ttc,n background_color=white,n mask=mask_imgn ).generate(data)n plt.imshow(wordcloud)n plt.axis(off)n plt.savefig(./heart.jpg, dpi=600)n
需要注意的是處理時,需要給 matplotlib 指定中文字體,否則會顯示亂碼,找到字體文件夾:C:WindowsFontsMicrosoft YaHei UI複製該字體,拷貝到 matplotlib 安裝目錄:C:Python27Libsite-packagesmatplotlibmpl-datafontsttf 下
差不多就這樣。
完整代碼可以在公眾號回復"h"下載。
本文首發於公眾號『一個程序員的微站』(id:VTtalk),分享 Python 乾貨和有溫度的內容博客地址:基於微博數據打造一顆「愛心」 - FooFish
推薦閱讀:
※第100篇文章紀念(? ?_?)?
※4行Python代碼獲取所在城市天氣預報
※【爬蟲】解決封IP問題:1.利用ADSL伺服器
※對豆瓣《戰狼2》87767 條短評做詞雲
※爬取Ajax動態載入和翻頁時url不變的網頁