如何用python爬取美團點評資料並做情感分析
自從18年10月底開始課餘在導師的公司實習,不知不覺入坑機器學習和深度學習已經小半年時間。目前的主要方向是NLP和資料探勘。
這期間接觸了許多新的知識,見識了火熱的深度學習的魅力和實際應用,也認識了很多浙大的牛人,有很多感觸。
這篇文章,是對我近期做的 情感分析demo 的一個總結;但正因為它簡單又內容豐富,相信會幫助即便外行的讀者,也能對爬蟲和深度學習有新的認識。
全文共計3800餘字,閱讀時間預計10-20分鐘不等。閱讀完本文,你將學習到:
01 如何安裝使用python
02 如何用python爬取資料
03 如何使用pandas、numpy做簡單的資料處理
04 如何呼叫bert-as-service,快速得到中文詞向量
05 如何使用深度學習框架keras建模,做簡單的情感分析
01 如何安裝使用Python
安裝 python
的方式很多,而 Mac os
和 Ubuntu
等作業系統甚至已經預裝了 python
。
但是,我還是強烈推薦你安裝 Anaconda
套裝 。它是一個開源的python發行版本,包含了180多個科學包及其依賴項,其中很多工具包對於後期機器學習的研究非常重要。所以第一次就安裝它,可以“一勞永逸”。

進入 Anaconda
官網的下載頁面,可以根據你使用的系統下載最新版本的 conda
。如果你想下載歷史版本的 Anaconda
,可以點選 此連結
此後,根據中文提示一步步安裝即可,非常簡單方便。

image.png
Windows
下稱“命令提示符”),我們使用
conda
建立一個虛擬環境,這樣可以和系統中原有的python環境相隔離。
如圖,我們建立了一個 python3.6
版本的虛擬環境,使用 conda env list
可以檢視我們當前所有虛擬環境(目前只有py36),然後 source activate py36
啟用它。

到此, python
最基礎的環境搭建全部完成啦。
02 如何用python爬取資料
學不學計算機,想必你都曾經聽過“ 爬蟲 ”這個詞。說實話,我當初第一次聽到這兩個字,想到的是一群蟲子在我身上爬,而起了一身雞皮疙瘩....
好!我們言歸正傳。在準備爬取資料前,我們得先對什麼是爬蟲有簡單的瞭解:
網路爬蟲(Web crawler),是一種按照一定的規則,自動地抓取全球資訊網資訊的程式或者指令碼,採集所有其能夠訪問到的頁面內容(包括文字、圖片、視訊、音訊等)
簡單的說,所謂爬蟲就是用程式去自動採(爬)集(取)網際網路上的公開內容。
而爬蟲之所以總是和 python
掛鉤,是因為 python
這一指令碼語言非常適合寫爬蟲程式碼。如果你問我有多簡單?
兩行程式碼就完事了!
import requests r = requests.get(url="http://www.baidu.com")
requests
庫會自動向我們指定的url連結(百度)發起http請求,並將結果返回到 r.content
中。
當然這只是最簡單的一種情況,爬取到的內容也不過是百度首頁的原始碼;但實際開發爬蟲時的核心內容,已經在這兩行程式碼裡完美呈現了,可以說剩下的都是“點綴”。
在我們的這個專案中,使用了一個比requests庫稍複雜的框架 Scrapy
,它是 python
最火熱的爬蟲框架(可能沒有之一),結構化的設計可以讓開發人員非常方便的根據專案需求進行修改。
如果對 Scrapy
有興趣的同學,我可以為你提供一些參考資料:
當然,我覺得最快的學習方式是 先簡單瞭解 scrapy
的理論基礎(如5大組成部分),然後進行專案實戰 (參考微博爬蟲專案,寫的挺完善)。
這裡的美團點評爬蟲,爬取的是杭州、上海、北京等5大城市各1000家餐館的前200條點評(合計約100w+評論資料),通過構造訪問 api
介面,提取 json
格式的資料。程式碼類似於長這樣:

由於本文的重點不是爬蟲講解,所以程式碼部分直接一帶而過。
在評論內容的篩選上,我只保留了4-5星和1-2星的評論,作為後期情感識別的訓練/測試資料。
最終爬取結果:

mongodb
中,省去了建表的麻煩。
如果嫌慢,我們還可以採取分散式的架構(如 scrapy-redis
),加快爬蟲的爬取速度。
耐心等待爬蟲執行結束,去資料庫中檢視爬蟲忠誠的為我們爬取的資料:

爬取結果
有了資料,接下來要做的就是資料預處理啦!
03 使用pandas、numpy做簡單的資料處理
很多人把 pandas
、 numpy
、 matplotlib
3個庫稱為python資料處理和視覺化的三劍客,因為它們真的功能強大又好用。這裡我們先介紹前兩個, matplotlib
留到第5小節。
之前我們爬取的資料還保留在 mongodb
中,我們可以用 mogoexport
或藉助資料庫視覺化軟體將其匯出到 csv
檔案中。
這裡為了簡化,我們分別匯出評分5星和評分1星的評論(剛好對應正負兩面情感)各6800條;在後續處理中,每種情感取6000條用作訓練(包含驗證集),剩餘800條作為測試。
我們分別匯出的資料命名為 10_star.csv
、 50_star.csv
,藉助 pandas
庫用一行程式碼匯入,並檢視前5行內容。
import pandas as pd df1 = pd.read_csv('./10_star.csv') df2 = pd.read_csv('./10_star.csv') print(df1.head()) print(df1.head())

執行結果
接下來,我們要遍歷 comment
列的每一行,過濾其中的非中文字元;再將字數大於10的評論加入一個列表。

資料過濾
這是對其中的負面評論的資料處理,正面評論處理類似。最後將資料直接整合在一起:
X_data = X_data1[:6000] + X_data2[:6000]# 訓練資料 X_test_data = X_data1[6000:6800] + X_data2[6000:6800]# 測試資料
請注意,這裡我們保證了 X_data
前6000條資料是負面的(來自X_data1),後6000條是正面的(來自X_data2)。 X_test_data
也同理。
得到訓練資料後,我們手工建立一個 labels
陣列(訓練標籤),前6000個元素是0,後6000個元素是1;再通過 numpy
庫轉換為 numpy陣列
,便於後期輸入到神經網路中。
import numpy as np y_data = [0 for i in range(6000)] + [1 for i in range(6000)] y_data = np.asarray(y_data, dtype=np.float32) y_test_data = [0 for i in range(800)] + [1 for i in range(800)] y_test_data = np.asarray(y_data, dtype=np.float32)
現在,聰明的你可能發現一個問題:我們的資料太有規律啦,正負情感剛好前後各佔了一半;假如我們輸入了前3000條到模型中,機器“機智的”全判斷為負面,能證明準確率就有100%了?
為了避免資料分佈不規律的現象,我們需要為資料進行“洗牌”(隨機打亂)。
還是藉助 numpy
,我們可以輕鬆實現這一過程。
X_train = [] y_train = [] X_test = [] y_test = [] nums = np.arange(12000) # 隨機打亂12000個訓練資料 np.random.shuffle(nums) for i in nums: X_train.append(X_data[i]) y_train.append(y_data[i]) # 隨機打亂1600個測試資料 nums_ = np.arange(1600) np.random.shuffle(nums_)# shuffle改變的是自身的內容 for i in nums_: X_test.append(X_test_data [i]) y_test.append(y_test_data [i]) # list轉Numpy陣列 X_train= np.asarray(X_train, dtype=np.float32) X_test= np.array(X_test, dtype=np.float32)
到此為止,簡單的資料預處理就結束了,是不是可以開始搭建我們的神經網路模型了?
別急!這兒我們的資料還全都是中文,即便是英文字母,計算機也一概不認識。所以,一位重量級的選手馬上就要登場和我們見面了。:clap::clap:
04 呼叫bert-as-service,快速得到中文詞向量
在自然語言處理任務中,首先需要考慮詞如何在計算機中表示。常見的表示方法有兩種
01 one-hot representation (獨熱編碼)
02 distribution representation
第一種是離散的表示方法,得到的是高維度的稀疏矩陣;第二種方法(Word Embedding)則是將詞表示成定長的連續稠密向量。想深入的同學,請利用好您的搜尋引擎(上網搜!)
從頭訓練一個有效的語言模型是耗時又耗能的過程。學習NLP的同學,一定知道去年底Google釋出的 Bert
模型。
本例中,我們藉助騰訊AI實驗室釋出的 bert-as-service
介面,讓你能簡單的通過兩行程式碼,即可使用預訓練好的bert模型生成句向量和ELMO風格的詞向量。
關於 bert-as-service
的官方介紹,可以點選檢視作者: 肖涵博士的Git倉庫 。
我們來看一看這兩行程式碼是怎麼實現的?
from bert_serving.client import BertClient bc = BertClient # 將待訓練的中文資料轉換為(,768)維的句向量 input_train = bc.encode(X_train)
覺得上面的內容不能馬上看懂?
沒關係,送上免費學習傳送門: 兩行程式碼玩轉Google BERT句向量詞向量 。寫的很詳細哦!
bert-as-service
將一個句子統一轉換成 768維
的句向量 ;最終我們得到的就是 12000 * 768
維度的句向量矩陣,也就是我們將輸入到神經網路模型的真正資料。
05 使用Keras,實現簡單的情感分析模型
雖然我們這裡跑的只是一個很小的demo,但是資料處理部分依然是整個工程中最耗時間的部分;實際開發中也往往如此。
有了處理後的資料,後邊的路一下暢通了許多,尤其是有 keras
這樣容易上手的工具。
Keras
是一個高層神經網路API,由純 python
編寫並使用 Tensorflow
, Theano
, CNTK
作為後端,以簡介、快速為設計原則。
直接使用 pip
即可快速安裝 Keras
和 Tensorflow
$ pip install keras $ pip install tensorflow
典型的 Keras
工作流程大致可以分為四步:
(1) 定義訓練資料:輸入張量和目標張量。
(2) 定義層組成的網路(或模型),將輸入對映到目標。
(3) 配置學習過程:選擇損失函式、優化器和需要監控的指標。
(4) 呼叫模型的 fit 方法在訓練資料上進行迭代
我們直接使用使用 Sequential
類來定義模型(僅用於層的線性堆疊,是最常見的網路架構)。
from keras.models import Sequential from keras.layers import Dense, Dropout import tensorflow as tf model = Sequential() # 搭建模型 model.add(Dense(32, activation='relu', input_shape=(768,))) model.add(Dropout(0.3)) model.add(Dense(32, activation='relu')) model.add(Dense(1, activation='sigmoid'))
對於簡單的二分類問題,模型使用 Dense
全連線層拼接已經夠用,最後的輸出就是一個數,代表了正面/負面情感的概率。同時防止過擬合,在模型中加入了 Dropout
層,
接下來,我們來指定模型使用的優化器和損失函式,以及訓練過程中想要監控的指標。
model.compile( loss='binary_crossentropy', optimizer=tf.train.AdamOptimizer(), metrics=['acc'] )
最後,通過 fit
方法將輸入資料的 Numpy陣列
傳入模型;請注意, 我們留出了20%的資料作為驗證集:
history = model.fit( X_train, y_train, epochs=30, batch_size=128, validation_split=0.2, verbose=1 )
我們的模型就開始愉快的迭代訓練啦!

訓練過程視覺化
loss
逐漸下降,準確度
acc
逐漸上升,直到最終趨於穩定,與我們的預期完全一致。
執行結束後,我們使用 matplotlib
庫將結果視覺化吧~
import matplotlib.pyplot as plt history_dict = history.history epochs = range(1, len(history_dict['acc']) + 1) # 繪圖部分 plt.figure() plt.plot(epochs, history_dict['acc'], 'b', label='acc') plt.plot(epochs, history_dict['val_acc'], 'bo', label='val_acc') plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.legend() plt.show()
分別畫出訓練過程中損失和精確度的變化,可以知道我們的模型確實從輸入資料中有效“學習”到了情感識別的模式。

image.png
dropout
預防過擬合,同時任務本身不算複雜,保證了我們的模型對於美團點評資料是好評還是差評有了
96%
的準確率!通過調參和加大模型的複雜度,這一結果應該會更高。
別忘了我們還有 1600條
資料被當作測試集還沒使用,也就是說模型還沒有“見過”這批資料。是時候派他們上場了!
呼叫 evaluate
方法實驗我們的測試資料:
test_loss = model.evaluate( X_test, y_test, batch_size=63, verbose=1 ) print(test_loss)
得到結果:
[0.07956909381508012, 0.9731250016018749]
它表示訓練損失和準確率分別為 0.07
和 97%
。
小結
本文帶你瞭解瞭如何安裝使用 python
,如何使用 python
爬取資料(構造爬蟲),如何處理資料以及使用 Keras
訓練模型,讓最後的結果視覺化。
可能涉及的內容比較多,又限於篇幅,對各個模組的內容只是管中窺豹,簡要帶過。
其實,這裡很多模組的內容遠不是一篇文章,甚至一本書就能全面詳細介紹的(如對於爬蟲的反爬措施部分,就可以寫一本書)。如果大家願意看,筆者會持續更新本專題下的文章。 對於本文談論的內容,你有沒有什麼不同的意見或者更好的建議?歡迎留言!
喜歡請不要吝嗇於點贊哈。