使用動態ip池爬取豆瓣約7萬部電影(附數據下載地址)

學爬蟲有一段時間了,作為一個懸疑片愛好者總是無限片荒,泛濫的Top250爬取以及填補不了我饑渴的內心。於是果然地決定:自己動手,爬完豆瓣,豐衣足食。

(一)反爬蟲策略分析:

之前其實有搜到過笑虎大大的文章:單機30分鐘抓取豆瓣電影7萬+數據:論爬蟲策略的重要性(附全部數據下載地址),但是發現單ip+隨機cookie的方法已經失效了。經過我不斷摸索,總結規律如下。

(1)單個ip不帶cookie訪問多次,ip不一會被封

(2)首次訪問返回cookie值,帶同一個cookie值連續訪問,幾分鐘被封;帶不同cookie值訪問,大約十分鐘之後,IP還是被封了。

(3)單個ip低速訪問(10s以上),不會被封

(二) 爬蟲策略分析:

簡單來說,有這麼幾個防止反爬方法:

  1. 帶隨機User Agent:最簡單,新手也都會
  2. 設置爬取間隔時間: 簡單,但是大大降低效率
  3. 帶可用cookie:可難可容易找規律,會需要帶上一些認證或者解密的數值去計算
  4. 使用代理:簡單粗暴有效,但是維護代理是個問題

由於單個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的

(三)代碼實現:

  1. 爬取過程:

首先找到豆瓣的索引頁面,通過查看源代碼發現,頁面內容是動態顯示的。通過谷歌瀏覽器自帶的F12->Network->XHR,找到json的入口。

動態頁面有兩種解析方式,一種直接用自帶的json庫,另一種selenium庫+Phantom JS來模擬真實瀏覽器。點開頁面,幸好~呼呼,沒用加密,直接用json庫就可以。

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一整數一變。每個頁面有相關電影名字,鏈接等。

打開單個電影頁面,比如:movie.douban.com/subjec。我所爬的信息如圖中所示。

某部最近看了喜歡的電影

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會導致爬蟲效率降低。

(四)成果

  1. 爬取結果:

四核開了四線程,爬蟲效率大概是十分鐘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里,大概是長這樣的:

某個document

如果想找個電影看看,如:

  • 評分高於7.5分
  • 觀看人數在1000~20000人之間
  • 科幻片

可以寫類似的query:

db.collection.find({$and: [{star: {$gte: 7.5}}, {pp: {$gte: 1000, $lte: 20000}},{type:re.compile(科幻)}]})

經過整合,清洗之後,總共有41960 部電影,以json格式從Mongodb里導出,打包放在百度雲盤:

鏈接: pan.baidu.com/s/12IiX4p 密碼: auw6

(五)最後:

感興趣的同學可移步我另外一個回答:

有哪些質量很高的冷門電影?

下一步會繼續研究scrapy+redis+mongodb走向分散式,提高爬蟲效率,以及做一些簡單的數據分析。

代碼我放在git上了,第一次用,不是特別會。

Muse1993/DoubanFilm_Collector

寫得挺渣……萌新求指教輕噴。

謝謝:)


推薦閱讀:

把出軌醜聞拍成電影,這場「不倫戀」太高調了!
追擊者在豆瓣評分是不是挺高的?
韓寒陳綺貞為電影《喜歡你》起唱,浪子這次愛的很深,旅人也要定居
豆瓣上對於電影《東方快車謀殺案》評價如何?
如何看待豆瓣電影的水軍行為?

TAG:豆瓣電影 | 爬蟲計算機網路 | python爬蟲 |