當前位置:
首頁 > 科技 > 擺脫劇荒!教你用 Python 一步步爬取豆瓣電影新榜單

擺脫劇荒!教你用 Python 一步步爬取豆瓣電影新榜單

本文以豆瓣電影(非TOP250)為例,從數據爬取、清洗與分析三個維度入手,詳解和還原數據爬取到分析的全鏈路。

作者 |周志鵬

責編 | 郭 芮

旁友,暑假,已經過了一大半了。

這個遙遠而炙熱的名詞,雖然和筆者這個上班狗已經沒有任何關係,但在房間穿著褲衩,吹著空調,吃著西瓜,看著電影,依然是假期最好的打開方式。現在褲衩、空調、西瓜都唾手可得,壓力全在電影這邊了。

關於電影推薦和排行,豆瓣是個好地方,只是電影TOP250排名實在是太經典,經典到有點老套了。筆者想來點新花樣,於是按默認的「評分最高」來排序,Emmm,結果好像比較小眾:

又按年代進行篩選,發現返回的結果和預期差的更遠了。

怎麼辦捏?不如我們自己對豆瓣電影進行更全面的爬取和分析,再DIY評分規則,結合電影上映年代做一個各年代TOP100電影排行榜。

數據爬取

1、網址規律探究

聽說看的人越多,評分越有說服力,所以我們進入導航頁,選擇「標記最多」。(雖然標記的多並不完全等於看的多,但也差不多了)

要找到網址變化規律,常規的套路就是先右鍵「審查元素」,然後通過不斷的點擊「載入更多」刷新頁面的方式來找規律。

網址規律異常的簡單,開頭URL不變,每翻一頁,start的數值增加20就OK了。

一頁是20部電影,開頭我們立下的FLAG是要爬取9000部電影,也就是爬取450頁。

2、單頁解析 循環爬取

豆瓣灰常貼心,每一頁都是JSON格式存儲的規整數據,爬取和清洗都省了不少事兒:

這裡我們只需要偽裝一下headers裡面的user-agent就可以愉快的爬取了:

直接上單頁解析的代碼:

然後我們寫一個循環,構造所需的450個基礎網址:

兩個湊一起,跑起來:

一個大號的功夫,包含電影ID、電影名稱、主演、導演、評分、標記人數和具體網址的數據已經爬好了:

下面,我們還想要批量訪問每一部電影,拿到有關電影各星級評分佔比等更豐富的信息,後續我們想結合評分分布來進行排序。

3、單部電影詳情爬取:

我們打開單部電影的網址,取巧做法是直接右鍵,查看源代碼,看看我們想要的欄位在不在源代碼中,畢竟,爬靜態的源代碼是最省力的。

電影名稱?在的!導演信息?在的!豆瓣評分?還是在的!一通CTRL F搜索發現,我們所有需要的欄位,全部在源代碼中。那爬取起來就太簡單了,這裡我們用xpath來解析:

第二步我們已經拿到了9000部電影所有的網址,只需寫個循環,批量訪問就可以了。然鵝,儘管設置了訪問時間間隔,爬取上千個頁面我們就會發現,豆娘還是會把我們給BAN(禁)掉。

回憶一下,我們沒有登錄,不需要cookies驗證,只是因為頻繁的訪問騷擾到了豆娘。那這個問題還是比較好解決的,此處不留爺,換個IP就留爺。細心的朋友已經發現了,上面針對單部電影的頁面解析,有一個默認IP參數,我們只需要在舊IP被禁後,傳入新的IP就可以了。

PS:代理IP如果展開講篇幅太長,網上有許多免費的IP代理(缺點是可用時間短,不穩定)和付費的IP代理(缺點是不免費)。另外,要強調一下這裡我們傳入的IP長這樣:{"https":"https://115.219.79.103:0000"}

電影頁面數據爬取結果如下:

數據清洗

1、基本信息表和電影內容表合併

base_info表裡面是我們批量抓取的電影基本信息,movie_info則是我們進入每一部電影,獲取到的感興趣欄位匯總,後面的分析是需要依賴兩張表進行的,所以我們合併之:

2、電影年份數據清洗:

我們發現之前爬取的上映時間數據不夠規整,前面都帶了一個「-」:

要把前面多餘的符號去掉,但發現無論怎麼用str.replace返回的都是Nan,原來這裡pandas把所有數字默認成負的,所以只需要把這一列所有數字乘-1即可:

3、評分分布規整:

最終我們是希望能夠把電影整體評分(如某電影8.9分)和不同評分等級(5星的佔比70%)結合起來分析的。而剛才爬取評分數據的時候,為了偷懶,用的是一個字典把各評分等級和對應的佔比給包起來了,然鵝,pandas默認把他當成了字元串,不能直接當做字典處理:

靈光一閃?這種字典形式的字元串,用JSON解析一下不就變字典了?HAVE A TRY:

結果,瘋狂報錯:

報錯貌似在提示我們是最外圍的引號錯誤導致了問題,目前我們用的是雙引號("{"a":1}")難道只能用單引號("{"a":1}")?先試試吧:

報錯解決了。接下來,我們把字典形式的評分拆成多列,例如每個星級對應一列,且百分比的格式變成數值型的,寫個循環函數,用apply應用一下即可:

現在我們的數據長這樣的:

OK,清洗到此告一段落。

數據分析

大家還記得開頭的FLAG嗎?我們要製作各年代TOP100電影排行榜。所以直接按照年代劃分電影,然後按照電影評分排個序不就完事了!

然鵝這聽起來有點話糙理也糙。如果只按照電影的總的評分來排序,會忽視掉內部評分細節的差異性,舉個例子,搏擊俱樂部:

總評分9.0分,打出5星好評的佔比60.9%,4星的有30.5%。

同為9分佳作,給美麗心靈打出5星好評的有56.0%,和搏擊俱樂部相比少了4.9%,而4星的人數則高出了6%。可以不負責任的做一個概括:兩部都是9分經典,但觀眾給搏擊俱樂部的5星傾向要高於美麗心靈。

GET到這個點,我們就可以對電影評分排序制定一個簡單的規則:先按照總評分排序,然後再對比5星人數佔比,如果一樣就對比4星,以此類推。這個評分排序邏輯用PYTHON做起來不要太簡單,一行代碼就搞定:

但是仔細看排序結果,我們會發現這樣排序的一些小瑕疵,一些高分電影其實是比較小眾的,比如「劇院魅影:25周年紀念演出」和「悲慘世界:25周年紀念演唱會」等。

而我們想要找的,是人民群眾所喜聞樂見的電影排名,這裡只有通過評分人數來代表人民的數量,我們先看一看所有電影的評分人數分布:

評分人數跨度極大,為了減少極值對於平均的影響,就讓中位數來衡量人民群眾是否喜聞樂見,所以我們只留下大於中位數的評分。

接著,看看歷年電影數量分布情況:

直到2000年初,篩選後的電影年上映數才逼近200,更早時期的電影好像20年加起來還不到100部。為了讓結果更加直觀,我們來按年代統計電影的上映時間。這裡涉及到給每部電影上映時間進行歸類,有點棘手啊...

絞盡腦細胞,終於找到了一個比較討巧的辦法,先構造年代標籤,再借用cut函數按十年的間隔切分上映時間,最後把標籤傳入參數。

得勒!數據直觀的反映出各年代上映量,20世紀80年代前真的是少得可憐。看到這裡,不由想到我們最開始立的那個「製作年代TOP100榜單」的FLAG,因為早期電影量的貧乏,是完全站不住腳的了。

不慌,一個優秀的數據分析師,一定是本著具體問題具體分析的精神來調整FLAG的:

基於年代上映量數據,我們從20世紀30年代開始製作排名;

為了避免有些年代電影過少,優化成各年代TOP 10%的電影推薦;

同時,為了避免近年電影過多,每個年代推薦的上限數不超過100部。

看到這三個條件,連一向自傲的潘大師(pandas)都不禁長嘆了口氣。然鵝大師之所以是大師,就是因為在他眼裡沒有什麼是不可能的。思考1分鐘後,確定了靈活篩選的套路:

根據上一步構造的century_f變數,結合每個年代上映電影量,不足1000部的篩選前10%,超過1000部的只篩選前100部,結果,就呼之而出了。

在附上代碼和榜單之前,我預感到大部分旁友是和我一樣懶的(不會仔細看榜單),所以先整理出各年代TOP5電影(有些年代不足TOP5),做一個精華版的歷史電影排行榜奉上:

從峰迴路轉、結尾讓人大呼牛逼的《控方證人》,到為無罪真理而辯的《十二怒漢》,再到家庭為重不怒自威的《教父》系列、重新詮釋希望和堅韌的《肖申克的救贖》以及將勵志提升到新高度的《阿甘正傳》。(筆者閱片尚淺,榜單上只看過這些)

每一部好的電影,都是一塊從高空墜落的石頭,它總能在人們的心湖上激起水花和漣漪,引起人們對生活、社會以及人性的思考。而爛片,就是從高空墜落的空礦泉水瓶,它墜勢洶洶,但最終只會浮在水面,讓看過的人心存芥蒂,感覺靈魂受到污染。

有了新的電影排名榜單,再也不用擔心劇荒了。

爬取、清洗、分析每一步詳解代碼和完整的電影排序名單,詳見:https://github.com/seizeeveryday/DA-cases/tree/master/DoubanMovies。

作者:周志鵬,2年數據分析,深切感受到數據分析的有趣和學習過程中缺少案例的無奈,遂新開公眾號「數據不吹牛」,定期更新數據分析相關技巧和有趣案例(含實戰數據集),歡迎大家關注交流。

聲明:本文為作者投稿,版權歸其所有。

【END】

熱 文推 薦

你點的每個「在看」,我都認真當成了喜歡

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

程序員偽裝 AI 編程,竟騙來 2 億的投資!
刷屏了!這篇Python學習貼,90%的程序員都用的上

TAG:CSDN |