如何用python爬取美團點評數(shù)據(jù)并做情感分析

自從18年10月底開始課余在導師的公司實習窟感,不知不覺入坑機器學習和深度學習已經(jīng)小半年時間。目前的主要方向是NLP和數(shù)據(jù)挖掘歉井。

這期間接觸了許多新的知識,見識了火熱的深度學習的魅力和實際應用哈误,也認識了很多浙大的牛人哩至,有很多感觸躏嚎。

這篇文章,是對我近期做的情感分析demo的一個總結(jié)菩貌;但正因為它簡單又內(nèi)容豐富卢佣,相信會幫助即便外行的讀者,也能對爬蟲和深度學習有新的認識箭阶。

全文共計3800余字虚茶,閱讀時間預計10分鐘。閱讀完本文仇参,你將學習到:

01 如何安裝使用python

02 如何用python爬取數(shù)據(jù)

03 如何使用pandas嘹叫、numpy做簡單的數(shù)據(jù)處理

04 如何調(diào)用bert-as-service,快速得到中文詞向量

05 如何使用深度學習框架keras建模诈乒,做簡單的情感分析

01 如何安裝使用Python

安裝python的方式很多罩扇,而Mac osUbuntu等操作系統(tǒng)甚至已經(jīng)預裝了python

但是怕磨,我還是強烈推薦你安裝Anaconda套裝喂饥。它是一個開源的python發(fā)行版本,包含了180多個科學包及其依賴項肠鲫,其中很多工具包對于后期機器學習的研究非常重要员帮。所以第一次就安裝它,可以“一勞永逸”导饲。

進入Anaconda官網(wǎng)的下載頁面捞高,可以根據(jù)你使用的系統(tǒng)下載最新版本的conda。如果你想下載歷史版本的Anaconda帜消,可以點擊此鏈接

此后棠枉,根據(jù)中文提示一步步安裝即可,非常簡單方便泡挺。

image.png
安裝完成后辈讶,進入終端(Windows下稱“命令提示符”),我們使用conda創(chuàng)建一個虛擬環(huán)境娄猫,這樣可以和系統(tǒng)中原有的python環(huán)境相隔離贱除。

如圖,我們創(chuàng)建了一個python3.6版本的虛擬環(huán)境媳溺,使用conda env list可以查看我們當前所有虛擬環(huán)境(目前只有py36)月幌,然后source activate py36激活它。

到此悬蔽,python最基礎的環(huán)境搭建全部完成啦扯躺。

02 如何用python爬取數(shù)據(jù)

學不學計算機,想必你都曾經(jīng)聽過“爬蟲”這個詞。說實話录语,我當初第一次聽到這兩個字倍啥,想到的是一群蟲子在我身上爬,起了一身雞皮疙瘩....

好澎埠!我們言歸正傳虽缕。在準備爬取數(shù)據(jù)前,我們得先對什么是爬蟲有簡單的了解:

網(wǎng)絡爬蟲(Web crawler)蒲稳,是一種按照一定的規(guī)則氮趋,自動地抓取萬維網(wǎng)信息的程序或者腳本,采集所有其能夠訪問到的頁面內(nèi)容(包括文本江耀、圖片剩胁、視頻、音頻等)

簡單的說决记,所謂爬蟲就是用程序去自動采(爬)集(却菁健)互聯(lián)網(wǎng)上的公開內(nèi)容。

而爬蟲之所以總是和python掛鉤系宫,是因為python這一腳本語言非常適合寫爬蟲代碼索昂。如果你問我有多簡單?

兩行代碼就完事了扩借!

import requests
r = requests.get(url="http://www.baidu.com")

requests庫會自動向我們指定的url鏈接(百度)發(fā)起http請求椒惨,并將結(jié)果返回到r.content中。

當然這只是最簡單的一種情況潮罪,爬取到的內(nèi)容也不過是百度首頁的源碼康谆;但實際開發(fā)爬蟲時的核心內(nèi)容,已經(jīng)在這兩行代碼里完美呈現(xiàn)了嫉到,可以說剩下的都是“點綴”沃暗。

在我們的這個項目中,使用了一個比requests庫稍復雜的框架Scrapy何恶,它是python最火熱的爬蟲框架孽锥,結(jié)構(gòu)化的設計可以讓開發(fā)人員非常方便的根據(jù)項目需求進行修改。

如果對 Scrapy有興趣的同學细层,我可以為你提供一些參考資料:

01 Scrapy官方文檔
02 《Python爬蟲開發(fā)與項目實戰(zhàn)》
03 構(gòu)建單機千萬級別的微博爬蟲系統(tǒng)

當然惜辑,我覺得最快的學習方式是先簡單了解scrapy的理論基礎(如5大組成部分),然后進行項目實戰(zhàn)(參考微博爬蟲項目疫赎,寫的挺完善)盛撑。

這里的美團點評爬蟲,爬取的是杭州捧搞、上海抵卫、北京等5大城市各1000家餐館的前200條點評(合計約100w+評論數(shù)據(jù))狮荔,通過構(gòu)造訪問api接口,提取json格式的數(shù)據(jù)陌僵。代碼類似于長這樣:

由于本文的重點不是爬蟲講解轴合,所以代碼部分直接一帶而過创坞。

在評論內(nèi)容的篩選上碗短,我只保留了4-5星和1-2星的評論,作為后期情感識別的訓練/測試數(shù)據(jù)题涨。

最終爬取結(jié)果:

我將評論數(shù)據(jù)存儲到mongodb中偎谁,省去了建表的麻煩。

如果嫌慢纲堵,我們還可以采取分布式的架構(gòu)(如scrapy-redis)巡雨,加快爬蟲的爬取速度。

耐心等待爬蟲運行結(jié)束席函,去數(shù)據(jù)庫中查看爬蟲忠誠的為我們爬取的數(shù)據(jù):


爬取結(jié)果

有了數(shù)據(jù)铐望,接下來要做的就是數(shù)據(jù)預處理啦!

03 使用pandas茂附、numpy做簡單的數(shù)據(jù)處理

很多人把pandas正蛙、numpymatplotlib3個庫稱為python數(shù)據(jù)處理和可視化的三劍客营曼,因為它們真的功能強大又好用乒验。這里我先介紹前兩個,matplotlib留到第5小節(jié)蒂阱。

我們爬取的數(shù)據(jù)保留在mongodb中锻全,我們可以用mogoexport或借助數(shù)據(jù)庫可視化軟件將其導出到csv文件中。

這里為了簡化录煤,我們分別導出評分5星和評分1星的評論(剛好對應正負兩面情感)各6800條鳄厌;在后續(xù)處理中,每種情感取6000條用作訓練(包含驗證集)妈踊,剩余800條作為測試了嚎。

我們分別導出的數(shù)據(jù)命名為10_star.csv50_star.csv响委,借助pandas庫用一行代碼導入新思,并查看前5行內(nèi)容。

import pandas as pd
df1 = pd.read_csv('./10_star.csv')
df2 = pd.read_csv('./10_star.csv')
print(df1.head())
print(df1.head())
運行結(jié)果

接下來赘风,我們要遍歷comment列的每一行夹囚,過濾其中的非中文字符;再將字數(shù)大于10的評論加入一個列表邀窃。

數(shù)據(jù)過濾

這是對其中的負面評論的數(shù)據(jù)處理荸哟,正面評論處理類似假哎。最后將數(shù)據(jù)直接整合在一起:

X_data = X_data1[:6000] + X_data2[:6000]              # 訓練數(shù)據(jù)
X_test_data = X_data1[6000:6800] + X_data2[6000:6800]      # 測試數(shù)據(jù)

請注意,這里我們保證了X_data前6000條數(shù)據(jù)是負面的(來自X_data1)鞍历,后6000條是正面的(來自X_data2)舵抹。X_test_data也同理。

得到訓練數(shù)據(jù)后劣砍,我們手工創(chuàng)建一個labels數(shù)組(訓練標簽)惧蛹,前6000個元素是0,后6000個元素是1刑枝;再通過numpy庫轉(zhuǎn)換為numpy數(shù)組香嗓,便于后期輸入到神經(jīng)網(wǎng)絡中。

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)

現(xiàn)在装畅,聰明的你可能發(fā)現(xiàn)一個問題:我們的數(shù)據(jù)太有規(guī)律啦靠娱,正負情感剛好前后各占了一半;假如我們輸入了前3000條到模型中掠兄,機器“機智的”全判斷為負面像云,能證明準確率就有100%了?

為了避免數(shù)據(jù)分布不規(guī)律的現(xiàn)象蚂夕,我們需要為數(shù)據(jù)進行“洗牌”(隨機打亂)迅诬。

還是借助numpy,我們可以輕松實現(xiàn)這一過程双抽。

X_train = []
y_train = []
X_test = []
y_test = []

nums = np.arange(12000)
# 隨機打亂12000個訓練數(shù)據(jù)
np.random.shuffle(nums)
for i in nums:
    X_train.append(X_data[i])
    y_train.append(y_data[i])

# 隨機打亂1600個測試數(shù)據(jù)
nums_ = np.arange(1600)
np.random.shuffle(nums_)  # shuffle改變的是自身的內(nèi)容
for i in nums_:
    X_test.append(X_test_data [i])
    y_test.append(y_test_data [i])

# list轉(zhuǎn)Numpy數(shù)組
X_train= np.asarray(X_train, dtype=np.float32)
X_test= np.array(X_test, dtype=np.float32)

到此為止百框,簡單的數(shù)據(jù)預處理就結(jié)束了,是不是可以開始搭建我們的神經(jīng)網(wǎng)絡模型了牍汹?

別急铐维!這兒我們的數(shù)據(jù)還全都是中文,即便是英文字母慎菲,計算機也一概不認識嫁蛇。所以,一位重量級的選手馬上就要登場和我們見面了露该。????

04 調(diào)用bert-as-service睬棚,快速得到中文詞向量

在自然語言處理任務中,首先需要考慮詞如何在計算機中表示解幼。常見的表示方法有兩種

01 one-hot representation (獨熱編碼)

02 distribution representation

第一種是離散的表示方法抑党,得到的是高維度的稀疏矩陣;第二種方法(Word Embedding)則是將詞表示成定長的連續(xù)稠密向量撵摆。想深入的同學底靠,請利用好您的搜索引擎(上網(wǎng)搜!)

從頭訓練一個有效的語言模型是耗時又耗能的過程特铝。學習NLP的同學暑中,一定知道去年底Google發(fā)布的Bert模型壹瘟。

本例中,我們借助騰訊AI實驗室發(fā)布的bert-as-service接口鳄逾,讓你能簡單的通過兩行代碼稻轨,即可使用預訓練好的bert模型生成句向量和ELMO風格的詞向量。

關(guān)于bert-as-service的官方介紹雕凹,可以點擊查看作者:肖涵博士的Git倉庫殴俱。

我們來看一看這兩行代碼是怎么實現(xiàn)的?

from bert_serving.client import BertClient
bc = BertClient
# 將待訓練的中文數(shù)據(jù)轉(zhuǎn)換為(请琳,768)維的句向量
input_train = bc.encode(X_train)

覺得上面的內(nèi)容不能馬上看懂粱挡?

沒關(guān)系,送上免費學習傳送門:兩行代碼玩轉(zhuǎn)Google BERT句向量詞向量俄精。寫的很詳細哦!

bert-as-service將一個句子統(tǒng)一轉(zhuǎn)換成768維的句向量榕堰;最終我們得到的就是12000 * 768維度的句向量矩陣竖慧,也就是我們將輸入到神經(jīng)網(wǎng)絡模型的真正數(shù)據(jù)。

05 使用Keras逆屡,實現(xiàn)簡單的情感分析模型

雖然我們這里跑的只是一個很小的demo圾旨,但是數(shù)據(jù)處理部分依然是整個工程中最耗時間的部分;實際開發(fā)中也往往如此魏蔗。

有了處理后的數(shù)據(jù)砍的,后邊的路一下暢通了許多,尤其是有keras這樣容易上手的工具莺治。

Keras是一個高層神經(jīng)網(wǎng)絡API廓鞠,由純python編寫并使用Tensorflow,Theano,CNTK作為后端,以簡介谣旁、快速為設計原則床佳。

直接使用pip即可快速安裝KerasTensorflow

$ pip install keras
$ pip install tensorflow

典型的Keras工作流程大致可以分為四步:

(1) 定義訓練數(shù)據(jù):輸入張量和目標張量。
(2) 定義層組成的網(wǎng)絡(或模型)榄审,將輸入映射到目標砌们。
(3) 配置學習過程:選擇損失函數(shù)、優(yōu)化器和需要監(jiān)控的指標搁进。
(4) 調(diào)用模型的 fit 方法在訓練數(shù)據(jù)上進行迭代

我們直接使用使用Sequential類來定義模型(僅用于層的線性堆疊浪感,是最常見的網(wǎng)絡架構(gòu))。

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全連接層拼接已經(jīng)夠用影兽,最后的輸出就是一個數(shù),代表了正面/負面情感的概率匆瓜。同時防止過擬合赢笨,在模型中加入了Dropout層未蝌,

接下來,我們來指定模型使用的優(yōu)化器和損失函數(shù)茧妒,以及訓練過程中想要監(jiān)控的指標萧吠。

model.compile(
    loss='binary_crossentropy',
    optimizer=tf.train.AdamOptimizer(),
    metrics=['acc']
)

最后,通過fit方法將輸入數(shù)據(jù)的Numpy數(shù)組傳入模型桐筏;請注意纸型,我們留出了20%的數(shù)據(jù)作為驗證集:

history = model.fit(
    X_train, y_train,
    epochs=30,
    batch_size=128,
    validation_split=0.2,
    verbose=1
)

我們的模型就開始愉快的迭代訓練啦!

訓練過程可視化

可以觀察到梅忌,隨著迭代次數(shù)增加狰腌,模型的損失loss逐漸下降,準確度acc逐漸上升牧氮,直到最終趨于穩(wěn)定琼腔,與我們的預期完全一致。

運行結(jié)束后踱葛,我們使用matplotlib庫將結(jié)果可視化吧~

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()

分別畫出訓練過程中損失和精確度的變化丹莲,可以知道我們的模型確實從輸入數(shù)據(jù)中有效“學習”到了情感識別的模式。

image.png

因為訓練數(shù)據(jù)不算太少尸诽,又加入了dropout預防過擬合甥材,同時任務本身不算復雜,保證了我們的模型對于美團點評數(shù)據(jù)是好評還是差評有了96%的準確率性含!通過調(diào)參和加大模型的復雜度洲赵,這一結(jié)果應該會更高。

別忘了我們還有1600條數(shù)據(jù)被當作測試集還沒使用商蕴,也就是說模型還沒有“見過”這批數(shù)據(jù)叠萍。是時候派他們上場了!

調(diào)用evaluate方法實驗我們的測試數(shù)據(jù):

test_loss = model.evaluate(
    X_test,
    y_test,
    batch_size=63,
    verbose=1
)
print(test_loss)

得到結(jié)果:
[0.07956909381508012, 0.9731250016018749]

它表示訓練損失和準確率分別為0.0797%究恤。


小結(jié)

本文帶你了解了如何安裝使用python俭令,如何使用python爬取數(shù)據(jù)(構(gòu)造爬蟲),如何處理數(shù)據(jù)以及使用Keras訓練模型部宿,讓最后的結(jié)果可視化抄腔。

可能涉及的內(nèi)容比較多,又限于篇幅理张,對各個模塊的內(nèi)容只是管中窺豹赫蛇,簡要帶過。

其實雾叭,這里很多模塊的內(nèi)容遠不是一篇文章悟耘,甚至一本書就能全面詳細介紹的(如對于爬蟲的反爬措施部分,就可以寫一本書)织狐。如果大家愿意看暂幼,筆者會持續(xù)更新本專題下的文章筏勒。對于本文談論的內(nèi)容,你有沒有什么不同的意見或者更好的建議旺嬉?歡迎留言管行!

喜歡請不要吝嗇于點贊哈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邪媳,一起剝皮案震驚了整個濱河市捐顷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌雨效,老刑警劉巖迅涮,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異徽龟,居然都是意外死亡叮姑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門顿肺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來戏溺,“玉大人,你說我怎么就攤上這事屠尊。” “怎么了耕拷?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵讼昆,是天一觀的道長。 經(jīng)常有香客問我骚烧,道長浸赫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任赃绊,我火速辦了婚禮既峡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碧查。我一直安慰自己运敢,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布忠售。 她就那樣靜靜地躺著传惠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪稻扬。 梳的紋絲不亂的頭發(fā)上卦方,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音泰佳,去河邊找鬼盼砍。 笑死尘吗,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的浇坐。 我是一名探鬼主播睬捶,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吗跋!你這毒婦竟也來了侧戴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤跌宛,失蹤者是張志新(化名)和其女友劉穎酗宋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疆拘,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蜕猫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了哎迄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片回右。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖漱挚,靈堂內(nèi)的尸體忽然破棺而出翔烁,到底是詐尸還是另有隱情,我是刑警寧澤旨涝,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布蹬屹,位于F島的核電站,受9級特大地震影響白华,放射性物質(zhì)發(fā)生泄漏慨默。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一弧腥、第九天 我趴在偏房一處隱蔽的房頂上張望厦取。 院中可真熱鬧,春花似錦管搪、人聲如沸虾攻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽台谢。三九已至,卻和暖如春岁经,著一層夾襖步出監(jiān)牢的瞬間朋沮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留樊拓,地道東北人纠亚。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像筋夏,于是被迫代替她去往敵國和親蒂胞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容