Python爬蟲入門 | 7 分類爬取豆瓣電影,解決動態載入問題

weixin_34234823發表於2017-12-15
8134750-261ecfac218f10a7.png
8134750-6e20f7398da33aac.png
8134750-bfa9b8bb7d7a4059.png


比如我們今天的案例,豆瓣電影分類頁面。根本沒有什麼翻頁,需要點選“載入更多”新的電影資訊,前面的黑科技瞬間被秒……

8134750-c5962af1621f526b.png


又比如知乎關注的人列表頁面:

8134750-4fd4765ee4b3d5e3.png


我複製了其中兩個人暱稱的 xpath:

//*[@id="Popover-35130-11238-toggle"]/a
//*[@id="Popover-35130-42416-toggle"]/a

竟然需要 ID 這種噁心的東西,規律失效。

8134750-f8af02bda22b7517.png
8134750-ce7f63dac69c4dc8.png


我們以豆瓣勵志分類下的電影為例,連結在這裡:
https://movie.douban.com/tag/#/?sort=T&range=0,10&tags=%E5%8A%B1%E5%BF%97

8134750-cbd9980e45bf072f.png
8134750-8a7e15d31f355c66.png

上面的標記應該是“分類”,而不是“排行榜”,更正一下。


首先要告訴你的是,這種動態載入的頁面,一般資料會在Network的 JS或者 XHR 類目裡。

8134750-b36cf529a691f62f.png

我們開啟開發者工具,看這一頁的 XHR裡沒有任何檔案,然後點選載入更多按鈕,看它給我們返回什麼資訊。

8134750-3be8c31b51c21e24.png


咦?返回了一個新的檔案,出於好奇,我們有必要看看究竟

右鍵點選 >> Open in new tab

有的網站 返回的 JS、XHR 資訊比較多,需要你去嘗試和篩選。

8134750-d8a298cde8b0e998.png


這個 json 頁面看起來就很親切了,包含電影名稱、導演、評分、演員、連結等資料。最關鍵的是,我仔細看了一遍頁面後發現,這一頁的電影資訊,正好是新載入出來的所有電影的資訊。

你的網頁看 json 很亂?不要著急,那是你的chrome沒有安裝jsonview這個外掛。證號為你準備好了,子按下方的雲盤下載、安裝就好:

連結:http://pan.baidu.com/s/1nvefj0t 密碼:13pm

8134750-ff8d9bb92cadfe9a.png

好了,又載入了兩次,不出意料地又載入出了兩頁 XHR 資訊,於是,滿懷期待地分別開啟它們。新載入的兩個頁面,和網頁顯示的電影資訊完全相同。

8134750-f455262c3f91234c.png
8134750-071aff3a1dd08750.png


我們再來看看 XHR 載入的這幾個頁面的 url:

#第二頁
https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start=20

#第三頁
https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start=40

#第四頁
https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start=60

比較後就可以輕鬆發現,這些頁面的 url 是有規律的:只有最後 start= 後面的數字在變化,而且是以20為步長遞增的,20正好對應每次載入出來的電影數量。


於是我們可以輕鬆地寫出頁面迴圈來爬取:

for a in range(3):    
  url='https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start={}'.format(a*20)

  # 用 a*20 表示每個頁面按 20 的步長遞增,只示例3個頁面,你可以按需求增加。


按照前面的套路寫出程式碼,並得到結果:

import requests
import json
import time

for a in range(3):
    url_visit = 'https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start={}'.format(a*20)
    file = requests.get(url_visit).json()   #這裡跟之前的不一樣,因為返回的是 json 檔案
    time.sleep(2)

    for i in range(20):
        dict=file['data'][i]   #取出字典中 'data' 下第 [i] 部電影的資訊
        urlname=dict['url']
        title=dict['title']
        rate=dict['rate']
        cast=dict['casts']
    
        print('{}  {}  {}  {}\n'.format(title,rate,'  '.join(cast),urlname))

爬取的資料如下:

8134750-3c6287ef6744e7ae.png


解釋一下程式碼中的一些細節:

file = requests.get(url).json() 

之前我們用的 .text 是需要網頁返回文字的資訊,而這裡返回的是 json檔案所以用 .json()

dict=file['data'][i] 
urlname=dict['url']

取出字典中的值,需要在方括號中指明值對應的鍵

'   '.join(cast)

因為有多名演員,這裡用了 join() 函式,在字串中間加入空格分隔。


當然,你也可以把爬下來的資訊存到本地:

8134750-a01c305e19113cd1.png

對電影評分進行排序,不久得到了所有的高分電影嗎?

8134750-8116f1eb351de645.png

8134750-d2e47e2d61f27e93.png

8134750-1210f33a7d109952.png

完整7節課程目錄:
Python爬蟲入門 | 1 Python環境的安裝
Python爬蟲入門 | 2 爬取豆瓣電影資訊
Python爬蟲入門 | 3 爬蟲必備Python知識
Python爬蟲入門 | 4 爬取豆瓣TOP250圖書資訊
Python爬蟲入門 | 5 爬取小豬短租租房資訊
Python爬蟲入門 | 6 將爬回來的資料存到本地
Python爬蟲入門 | 7 分類爬取豆瓣電影,解決動態載入問題

白白~

相關文章