使用動態ip池爬取豆瓣約7萬部電影(附數據下載地址)
學爬蟲有一段時間了,作為一個懸疑片愛好者總是無限片荒,泛濫的Top250爬取以及填補不了我饑渴的內心。於是果然地決定:自己動手,爬完豆瓣,豐衣足食。
(一)反爬蟲策略分析:
之前其實有搜到過笑虎大大的文章:單機30分鐘抓取豆瓣電影7萬+數據:論爬蟲策略的重要性(附全部數據下載地址),但是發現單ip+隨機cookie的方法已經失效了。經過我不斷摸索,總結規律如下。
(1)單個ip不帶cookie訪問多次,ip不一會被封
(2)首次訪問返回cookie值,帶同一個cookie值連續訪問,幾分鐘被封;帶不同cookie值訪問,大約十分鐘之後,IP還是被封了。
(3)單個ip低速訪問(10s以上),不會被封
(二) 爬蟲策略分析:
簡單來說,有這麼幾個防止反爬方法:
- 帶隨機User Agent:最簡單,新手也都會
- 設置爬取間隔時間: 簡單,但是大大降低效率
- 帶可用cookie:可難可容易找規律,會需要帶上一些認證或者解密的數值去計算
- 使用代理:簡單粗暴有效,但是維護代理是個問題
由於單個ip怎麼樣都會被封,所以我投向了代理的懷抱。爬蟲策略大致如下:
三個隨機:隨機UA,隨機代理,隨機cookie
網上免費代理一抓一大把,質量低下,不穩定,一開始自己寫了個proxypool,來過濾各大網站可能的ip再去爬,好不容易抓到一些能用,過了一會,這些ip又失效,或者又被封。最後遂決定還是得搞個動態的ip池。
- 對於使用免費代理:
可以參考git上的一個開源項目:jhao104/proxy。用了幾個類似的,感覺這個是最好的,它主要用flask做了一個api來實時刷新可用ip,不僅可以抓取各大主流免費代理ip,還能定時檢驗ip的可用性。但是這個項目還是有一個問題,比如當我設定抓取的間隔為10秒之後,執行任務的時間可能大於10s,會報一個warning引發整個程序暫停。
- 對於使用付費代理:
我個人不想再用免費低質的ip,遂買了那種包天的套餐,後來又醜陋地膜改了下這個jhao104/proxy的開源項目,只留下主要api+抓取proxy+資料庫的功能,每5秒一刷10個ip,爽歪歪~ 用付費代理的朋友可以參考下我的方法~proxy豐富的話,爬取數據時候可以不需要sleep的
(三)代碼實現:
- 爬取過程:
首先找到豆瓣的索引頁面,通過查看源代碼發現,頁面內容是動態顯示的。通過谷歌瀏覽器自帶的F12->Network->XHR,找到json的入口。
動態頁面有兩種解析方式,一種直接用自帶的json庫,另一種selenium庫+Phantom JS來模擬真實瀏覽器。點開頁面,幸好~呼呼,沒用加密,直接用json庫就可以。
json網址的格式大概是這樣的:
https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start=20&genres=%E5%96%9C%E5%89%A7
通過觀察,發現start=用來控制頁數,每個頁面有20部電影,20一整數一變。每個頁面有相關電影名字,鏈接等。
打開單個電影頁面,比如:https://movie.douban.com/subject/1292332/。我所爬的信息如圖中所示。
OK,大致思路來了。首先我們獲取每個json頁面的film信息,當json頁面沒有返回內容時候,解析停止,再去逐條分析單個電影靜態頁面的信息,打包入庫。
2. 幾個關鍵點:
- 解析方式:選了xpath,效率比某soup高很多,正則解析效率最高,但是開發效率較低(其實是我背不出
- 多線程:爬蟲算是IO型任務,使用多線程。用的是multiprocessing.dummy,似乎鮮為人知,比threading感覺使用上簡單一點,不是很明白兩者之間的區別?之後會嘗試下和threading比比效率。
- MongoDB: Proxy和電影的信息都存在Mongodb里,其實用redis存proxy更好,但是我不高興開那麼多資料庫了,後來發現mongodb似乎各種不穩定……有個topology was detroyed的錯誤時常發生導致資料庫失聯,有老鐵知道這是為啥嘛?
- 爬proxy時間間隔:這個其實還挺重要,因為代理有效時效有限(我買的是保證五分鐘),最好的效果應該是代理池裡數量稍大於實際用量,也就是假設proxy可用率為50%,5秒用壞一個proxy,五分鐘proxy失效,那麼大概設定平均略小於2.5秒左右刷新1個proxy比較好。如果proxy在資料庫里冗餘,大量失效proxy會導致爬蟲效率降低。
(四)成果
- 爬取結果:
四核開了四線程,爬蟲效率大概是十分鐘400部左右,所以真的不明白為什麼@笑虎大大可以半小時爬70000部,難道他的mac是100核的???
總之,大概加起來爬了二十多個小時終於爬完了……成果如下。
劇情片: 9,843部
喜劇片: 8,912部
愛情片: 7,714部
動作片: 6,065部
驚悚片: 5,776部
犯罪片: 4,610部
恐怖片: 4,113部
懸疑片: 3,895部
冒險片: 3,060部
奇幻片: 2,842部
科幻片: 2,665部
戰爭片: 1,822部
傳記片: 1,531部
歷史片: 1,464部
音樂片: 1,305部
同性片: 1,267部
歌舞片: 924部
情色片: 517部
西部片: 407部
武俠片: 377部
災難片: 159部
2. 查詢使用
數據在Mongodb里,大概是長這樣的:
如果想找個電影看看,如:
- 評分高於7.5分
- 觀看人數在1000~20000人之間
- 科幻片
可以寫類似的query:
db.collection.find({$and: [{star: {$gte: 7.5}}, {pp: {$gte: 1000, $lte: 20000}},{type:re.compile(科幻)}]})
經過整合,清洗之後,總共有41960 部電影,以json格式從Mongodb里導出,打包放在百度雲盤:
鏈接: https://pan.baidu.com/s/12IiX4p_fLg8CyidAjl8_Zw 密碼: auw6
(五)最後:
感興趣的同學可移步我另外一個回答:
有哪些質量很高的冷門電影?
下一步會繼續研究scrapy+redis+mongodb走向分散式,提高爬蟲效率,以及做一些簡單的數據分析。
代碼我放在git上了,第一次用,不是特別會。
Muse1993/DoubanFilm_Collector
寫得挺渣……萌新求指教輕噴。
謝謝:)
推薦閱讀:
※把出軌醜聞拍成電影,這場「不倫戀」太高調了!
※追擊者在豆瓣評分是不是挺高的?
※韓寒陳綺貞為電影《喜歡你》起唱,浪子這次愛的很深,旅人也要定居
※豆瓣上對於電影《東方快車謀殺案》評價如何?
※如何看待豆瓣電影的水軍行為?