Python 爬蟲實(shí)踐:《戰(zhàn)狼2》豆瓣影評分析

簡介

剛接觸python不久妈候,做一個小項(xiàng)目來練練手综看。前幾天看了《戰(zhàn)狼2》,發(fā)現(xiàn)它在最新上映的電影里面是排行第一的馒索,如下圖所示莹妒。準(zhǔn)備把豆瓣上對它的影評做一個分析。

目標(biāo)總覽

主要做了三件事:

抓取網(wǎng)頁數(shù)據(jù)

清理數(shù)據(jù)

用詞云進(jìn)行展示

使用的python版本是3.5.

一绰上、抓取網(wǎng)頁數(shù)據(jù)

第一步要對網(wǎng)頁進(jìn)行訪問旨怠,python中使用的是urllib庫。代碼如下:

from?urllib?import?request

resp?=?request.urlopen('https://movie.douban.com/nowplaying/hangzhou/')

html_data?=?resp.read().decode('utf-8')

其中https://movie.douban.com/nowplaying/hangzhou/是豆瓣最新上映的電影頁面蜈块,可以在瀏覽器中輸入該網(wǎng)址進(jìn)行查看鉴腻。

html_data是字符串類型的變量,里面存放了網(wǎng)頁的html代碼百揭。

輸入print(html_data)可以查看爽哎,如下圖所示:

第二步,需要對得到的html代碼進(jìn)行解析器一,得到里面提取我們需要的數(shù)據(jù)课锌。

在python中使用BeautifulSoup庫進(jìn)行html代碼的解析。

(注:如果沒有安裝此庫祈秕,則使用pip install BeautifulSoup進(jìn)行安裝即可C煜汀)

BeautifulSoup使用的格式如下:

BeautifulSoup(html,"html.parser")

第一個參數(shù)為需要提取數(shù)據(jù)的html,第二個參數(shù)是指定解析器请毛,然后使用find_all()讀取html標(biāo)簽中的內(nèi)容志鞍。

但是html中有這么多的標(biāo)簽,該讀取哪些標(biāo)簽?zāi)胤椒拢科鋵?shí)固棚,最簡單的辦法是我們可以打開我們爬取網(wǎng)頁的html代碼,然后查看我們需要的數(shù)據(jù)在哪個html標(biāo)簽里面仙蚜,再進(jìn)行讀取就可以了此洲。如下圖所示:

從上圖中可以看出在div id=”nowplaying“標(biāo)簽開始是我們想要的數(shù)據(jù),里面有電影的名稱鳍征、評分黍翎、主演等信息。所以相應(yīng)的代碼編寫如下:

from?bs4?import?BeautifulSoup?as?bs

soup?=?bs(html_data,?'html.parser')????

nowplaying_movie?=?soup.find_all('div',?id='nowplaying')

nowplaying_movie_list?=?nowplaying_movie[0].find_all('li',?class_='list-item')

其中nowplaying_movie_list 是一個列表艳丛,可以用print(nowplaying_movie_list[0])查看里面的內(nèi)容匣掸,如下圖所示:

在上圖中可以看到data-subject屬性里面放了電影的id號碼,而在img標(biāo)簽的alt屬性里面放了電影的名字氮双,因此我們就通過這兩個屬性來得到電影的id和名稱碰酝。(注:打開電影短評的網(wǎng)頁時需要用到電影的id,所以需要對它進(jìn)行解析)戴差,編寫代碼如下:

nowplaying_list?=?[]

for?item?in?nowplaying_movie_list:????????

????????nowplaying_dict?=?{}????????

????????nowplaying_dict['id']?=?item['data-subject']?

????????for?tag_img_item?in?item.find_all('img'):????????????

????????????nowplaying_dict['name']?=?tag_img_item['alt']????????????

????????????nowplaying_list.append(nowplaying_dict)

其中列表nowplaying_list中就存放了最新電影的id和名稱送爸,可以使用print(nowplaying_list)進(jìn)行查看,如下圖所示:

可以看到和豆瓣網(wǎng)址上面是匹配的。這樣就得到了最新電影的信息了袭厂。接下來就要進(jìn)行對最新電影短評進(jìn)行分析了墨吓。例如《戰(zhàn)狼2》的短評網(wǎng)址為:https://movie.douban.com/subject/26363254/comments?start=0&limit=20

其中26363254就是電影的id,start=0表示評論的第0條評論纹磺。

接下來接對該網(wǎng)址進(jìn)行解析了帖烘。打開上圖中的短評頁面的html代碼,我們發(fā)現(xiàn)關(guān)于評論的數(shù)據(jù)是在div標(biāo)簽的comment屬性下面橄杨,如下圖所示:

因此對此標(biāo)簽進(jìn)行解析秘症,代碼如下:

requrl?=?'https://movie.douban.com/subject/'?+?nowplaying_list[0]['id']?+?'/comments'?+'?'?+'start=0'?+?'&limit=20'

resp?=?request.urlopen(requrl)

html_data?=?resp.read().decode('utf-8')

soup?=?bs(html_data,?'html.parser')

comment_div_lits?=?soup.find_all('div',?class_='comment')

此時在comment_div_lits 列表中存放的就是div標(biāo)簽和comment屬性下面的html代碼了。在上圖中還可以發(fā)現(xiàn)在p標(biāo)簽下面存放了網(wǎng)友對電影的評論式矫,如下圖所示:

因此對comment_div_lits 代碼中的html代碼繼續(xù)進(jìn)行解析乡摹,代碼如下:

eachCommentList?=?[];

for?item?in?comment_div_lits:?

????????if?item.find_all('p')[0].string?is?not?None:?

????????????eachCommentList.append(item.find_all('p')[0].string)

使用print(eachCommentList)查看eachCommentList列表中的內(nèi)容,可以看到里面存里我們想要的影評采转。如下圖所示:

好的聪廉,至此我們已經(jīng)爬取了豆瓣最近播放電影的評論數(shù)據(jù),接下來就要對數(shù)據(jù)進(jìn)行清洗和詞云顯示了氏义。

二锄列、數(shù)據(jù)清洗

為了方便進(jìn)行數(shù)據(jù)進(jìn)行清洗,我們將列表中的數(shù)據(jù)放在一個字符串?dāng)?shù)組中惯悠,代碼如下:

comments?=?''

for?k?in?range(len(eachCommentList)):

????comments?=?comments?+?(str(eachCommentList[k])).strip()

使用print(comments)進(jìn)行查看邻邮,如下圖所示:

可以看到所有的評論已經(jīng)變成一個字符串了,但是我們發(fā)現(xiàn)評論中還有不少的標(biāo)點(diǎn)符號等克婶。這些符號對我們進(jìn)行詞頻統(tǒng)計時根本沒有用筒严,因此要將它們清除。所用的方法是正則表達(dá)式情萤。python中正則表達(dá)式是通過re模塊來實(shí)現(xiàn)的鸭蛙。代碼如下:

import?re


pattern?=?re.compile(r'[\u4e00-\u9fa5]+')

filterdata?=?re.findall(pattern,?comments)

cleaned_comments?=?''.join(filterdata)

繼續(xù)使用print(cleaned_comments)語句進(jìn)行查看,如下圖所示:

我們可以看到此時評論數(shù)據(jù)中已經(jīng)沒有那些標(biāo)點(diǎn)符號了筋岛,數(shù)據(jù)變得“干凈”了很多娶视。

因此要進(jìn)行詞頻統(tǒng)計,所以先要進(jìn)行中文分詞操作睁宰。在這里我使用的是結(jié)巴分詞肪获。如果沒有安裝結(jié)巴分詞,可以在控制臺使用pip install jieba進(jìn)行安裝柒傻。(注:可以使用pip list查看是否安裝了這些庫)孝赫。代碼如下所示:

import?jieba????#分詞包

import?pandas?as?pd??


segment?=?jieba.lcut(cleaned_comments)

words_df=pd.DataFrame({'segment':segment})

因?yàn)榻Y(jié)巴分詞要用到pandas,所以我們這里加載了pandas包红符∏啾可以使用words_df.head()查看分詞之后的結(jié)果伐债,如下圖所示:

從上圖可以看到我們的數(shù)據(jù)中有“看”、“太”致开、“的”等虛詞(停用詞)峰锁,而這些詞在任何場景中都是高頻時,并且沒有實(shí)際的含義喇喉,所以我們要他們進(jìn)行清除祖今。

我把停用詞放在一個stopwords.txt文件中,將我們的數(shù)據(jù)與停用詞進(jìn)行比對即可(注:只要在百度中輸入stopwords.txt拣技,就可以下載到該文件)。去停用詞代碼如下代碼如下:

stopwords=pd.read_csv("stopwords.txt",index_col=False,quoting=3,sep="\t",names=['stopword'],?encoding='utf-8')#quoting=3全不引用

words_df=words_df[~words_df.segment.isin(stopwords.stopword)]

繼續(xù)使用words_df.head()語句來查看結(jié)果耍目,如下圖所示膏斤,停用詞已經(jīng)被出去了。

接下來就要進(jìn)行詞頻統(tǒng)計了邪驮,代碼如下:

import?numpy????#numpy計算包

words_stat=words_df.groupby(by=['segment'])['segment'].agg({"計數(shù)":numpy.size})

words_stat=words_stat.reset_index().sort_values(by=["計數(shù)"],ascending=False)

用words_stat.head()進(jìn)行查看莫辨,結(jié)果如下:

由于我們前面只是爬取了第一頁的評論,所以數(shù)據(jù)有點(diǎn)少毅访,在最后給出的完整代碼中沮榜,我爬取了10頁的評論,所數(shù)據(jù)還是有參考價值喻粹。

三蟆融、用詞云進(jìn)行顯示

代碼如下:

import?matplotlib.pyplot?as?plt

%matplotlib?inline


import?matplotlib

matplotlib.rcParams['figure.figsize']?=?(10.0,?5.0)

from?wordcloud?import?WordCloud#詞云包


wordcloud=WordCloud(font_path="simhei.ttf",background_color="white",max_font_size=80)?#指定字體類型、字體大小和字體顏色

word_frequence?=?{x[0]:x[1]?for?x?in?words_stat.head(1000).values}

word_frequence_list?=?[]

for?key?in?word_frequence:

????temp?=?(key,word_frequence[key])

????word_frequence_list.append(temp)


wordcloud=wordcloud.fit_words(word_frequence_list)

plt.imshow(wordcloud)

其中simhei.ttf使用來指定字體的守呜,可以在百度上輸入simhei.ttf進(jìn)行下載后型酥,放入程序的根目錄即可。顯示的圖像如下:

到此為止查乒,整個項(xiàng)目的介紹就結(jié)束了凑保。由于自己也還是個初學(xué)者统扳,接觸python不久,代碼寫的并不好。而且第一次寫技術(shù)博客岸更,表達(dá)的有些冗余,請大家多多包涵史汗,有不對的地方蛮艰,請大家批評指正。以后我也會將自己做的小項(xiàng)目以這種形式寫在博客上和大家一起交流拒担!最后貼上完整的代碼嘹屯。

完整代碼

#coding:utf-8

__author__?=?'hang'


import?warnings

warnings.filterwarnings("ignore")

import?jieba????#分詞包

import?numpy????#numpy計算包

import?codecs?#codecs提供的open方法來指定打開的文件的語言編碼,它會在讀取的時候自動轉(zhuǎn)換為內(nèi)部unicode?

import?re

import?pandas?as?pd??

import?matplotlib.pyplot?as?plt

from?urllib?import?request

from?bs4?import?BeautifulSoup?as?bs

%matplotlib?inline


import?matplotlib

matplotlib.rcParams['figure.figsize']?=?(10.0,?5.0)

from?wordcloud?import?WordCloud#詞云包


#分析網(wǎng)頁函數(shù)

def?getNowPlayingMovie_list():?

????resp?=?request.urlopen('https://movie.douban.com/nowplaying/hangzhou/')????????

????html_data?=?resp.read().decode('utf-8')????

????soup?=?bs(html_data,?'html.parser')????

????nowplaying_movie?=?soup.find_all('div',?id='nowplaying')????????

????nowplaying_movie_list?=?nowplaying_movie[0].find_all('li',?class_='list-item')????

????nowplaying_list?=?[]????

????for?item?in?nowplaying_movie_list:????????

????????nowplaying_dict?=?{}????????

????????nowplaying_dict['id']?=?item['data-subject']?

????????for?tag_img_item?in?item.find_all('img'):????????????

????????????nowplaying_dict['name']?=?tag_img_item['alt']????????????

????????????nowplaying_list.append(nowplaying_dict)????

????return?nowplaying_list


#爬取評論函數(shù)

def?getCommentsById(movieId,?pageNum):?

????eachCommentList?=?[];

????if?pageNum>0:?

?start?=?(pageNum-1)?*?20

????else:?

????????return?False

????requrl?=?'https://movie.douban.com/subject/'?+?movieId?+?'/comments'?+'?'?+'start='?+?str(start)?+?'&limit=20'

????print(requrl)

????resp?=?request.urlopen(requrl)

????html_data?=?resp.read().decode('utf-8')

????soup?=?bs(html_data,?'html.parser')

????comment_div_lits?=?soup.find_all('div',?class_='comment')

????for?item?in?comment_div_lits:?

????????if?item.find_all('p')[0].string?is?not?None:?

????????????eachCommentList.append(item.find_all('p')[0].string)

????return?eachCommentList


def?main():

????#循環(huán)獲取第一個電影的前10頁評論

????commentList?=?[]

????NowPlayingMovie_list?=?getNowPlayingMovie_list()

????for?i?in?range(10):????

????????num?=?i?+?1

????????commentList_temp?=?getCommentsById(NowPlayingMovie_list[0]['id'],?num)

????????commentList.append(commentList_temp)


????#將列表中的數(shù)據(jù)轉(zhuǎn)換為字符串

????comments?=?''

????for?k?in?range(len(commentList)):

????????comments?=?comments?+?(str(commentList[k])).strip()


????#使用正則表達(dá)式去除標(biāo)點(diǎn)符號

????pattern?=?re.compile(r'[\u4e00-\u9fa5]+')

????filterdata?=?re.findall(pattern,?comments)

????cleaned_comments?=?''.join(filterdata)


????#使用結(jié)巴分詞進(jìn)行中文分詞

????segment?=?jieba.lcut(cleaned_comments)

????words_df=pd.DataFrame({'segment':segment})


????#去掉停用詞

????stopwords=pd.read_csv("stopwords.txt",index_col=False,quoting=3,sep="\t",names=['stopword'],?encoding='utf-8')#quoting=3全不引用

????words_df=words_df[~words_df.segment.isin(stopwords.stopword)]


????#統(tǒng)計詞頻

????words_stat=words_df.groupby(by=['segment'])['segment'].agg({"計數(shù)":numpy.size})

????words_stat=words_stat.reset_index().sort_values(by=["計數(shù)"],ascending=False)


????#用詞云進(jìn)行顯示

????wordcloud=WordCloud(font_path="simhei.ttf",background_color="white",max_font_size=80)

????word_frequence?=?{x[0]:x[1]?for?x?in?words_stat.head(1000).values}


????word_frequence_list?=?[]

????for?key?in?word_frequence:

????????temp?=?(key,word_frequence[key])

????????word_frequence_list.append(temp)


????wordcloud=wordcloud.fit_words(word_frequence_list)

????plt.imshow(wordcloud)


#主函數(shù)

main()

結(jié)果顯示如下:

上圖基本反映了《戰(zhàn)狼2》這部電影的情況从撼。

如果你在學(xué)習(xí)Python的過程當(dāng)中有遇見任何問題州弟,可以加入我的python交流學(xué)習(xí)qq群:250933691钧栖,多多交流問題,互幫互助婆翔,群里有不錯的學(xué)習(xí)教程和開發(fā)工具拯杠。學(xué)習(xí)python有任何問題(學(xué)習(xí)方法,學(xué)習(xí)效率啃奴,如何就業(yè))潭陪,可以隨時來咨詢我,如果你想學(xué)習(xí)大數(shù)據(jù)開發(fā)技術(shù)最蕾,也歡迎加入大數(shù)據(jù)學(xué)習(xí)交流qq群458345782依溯,每天與大家分享學(xué)習(xí)資源哦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瘟则,一起剝皮案震驚了整個濱河市黎炉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌醋拧,老刑警劉巖慷嗜,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異丹壕,居然都是意外死亡庆械,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門菌赖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缭乘,“玉大人,你說我怎么就攤上這事盏袄》蘧” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵辕羽,是天一觀的道長逛尚。 經(jīng)常有香客問我,道長刁愿,這世上最難降的妖魔是什么绰寞? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮铣口,結(jié)果婚禮上滤钱,老公的妹妹穿的比我還像新娘。我一直安慰自己脑题,他們只是感情好件缸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叔遂,像睡著了一般他炊。 火紅的嫁衣襯著肌膚如雪争剿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天痊末,我揣著相機(jī)與錄音蚕苇,去河邊找鬼。 笑死凿叠,一個胖子當(dāng)著我的面吹牛涩笤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盒件,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蹬碧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锰茉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤切心,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后片吊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绽昏,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年俏脊,在試婚紗的時候發(fā)現(xiàn)自己被綠了全谤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡爷贫,死狀恐怖认然,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漫萄,我是刑警寧澤卷员,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站腾务,受9級特大地震影響毕骡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岩瘦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一未巫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧启昧,春花似錦叙凡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽跛璧。三九已至,卻和暖如春饼拍,著一層夾襖步出監(jiān)牢的瞬間赡模,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工师抄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留漓柑,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓叨吮,卻偏偏與公主長得像辆布,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子茶鉴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355

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