使用python爬蟲實(shí)現(xiàn)抓取動態(tài)加載數(shù)據(jù)
確定網(wǎng)站類型
首先要明確豆瓣電影網(wǎng)站(movie.douban.com)的類型,即是動態(tài)還是靜態(tài)。檢查方法:右鍵查看網(wǎng)頁源碼 —> 搜索“辛德勒的名單”關(guān)鍵字,如下圖所示:
圖1:分析網(wǎng)站類型
最終發(fā)現(xiàn)源碼頁中沒有出現(xiàn)想要抓取的數(shù)據(jù),只有一大堆的 JS 代碼,由此確定該網(wǎng)站為動態(tài)網(wǎng)站。
影片詳情信息
接下來,使用快捷鍵 F12 打開控制臺進(jìn)行抓包,點(diǎn)擊NetWork
選項(xiàng)卡 —>XHR
選項(xiàng) —> Preview
選項(xiàng)卡 —> 刷新當(dāng)前頁面抓取數(shù)據(jù)包,如下圖所示:
圖2:抓取動態(tài)網(wǎng)站數(shù)據(jù)包
從圖 2 可知,我們想要抓取的數(shù)據(jù)取全部包含在當(dāng)前的數(shù)據(jù)包中。當(dāng)我們向下滾動鼠標(biāo)滑輪時(shí),左側(cè)欄內(nèi)的數(shù)據(jù)包會實(shí)現(xiàn)自動加載,這是使用 Ajax 異步加載技術(shù)實(shí)現(xiàn)的。
通過查看數(shù)據(jù) Headers 選項(xiàng)可以明確 url 地址、查詢參數(shù)等信息,如下所示:
圖3:分析Headers信息
從上圖可以得知請求的基準(zhǔn) URL (由于還未拼接查詢參數(shù),所以稱之為基準(zhǔn) URL),如下所示:
'https://movie.douban.com/j/chart/top_list?'
繼續(xù)滾動鼠標(biāo)滑輪可知查詢參數(shù)具有如下規(guī)律:
type: 4 # 電影類型 interval_id: 100:90 #代表網(wǎng)頁上滑動條的百分比(好于100%-90%的歷史片) action: '' # 空 start: 0 # 每次加載電影的起始索引值 0 20 40 60 limit: 20 # 每次加載的電影數(shù)量,1為初始值,后續(xù)加載時(shí)20固定不變
注意:尋找規(guī)律時(shí),后加載出來的數(shù)據(jù)包會排在最前面,除去第一個數(shù)據(jù)包外,其余數(shù)據(jù)包如下所示:
圖4:尋找查詢參數(shù)值的規(guī)律
影片總數(shù)量
注意:第一個數(shù)據(jù)包反映了每個類型中電影的總數(shù)量,其 url 與響應(yīng)信息如下:
請求的URL地址 : https://movie.douban.com/j/chart/top_list_count?type=4&interval_id=100%3A90 Response信息:{"playable_count":41,"total":104,"unwatched_count":104}
影片類型與類型碼
影片的類型與類型碼包含在電影排行榜的主界面中,如下所示:
圖5:影片類型與類型碼
分析上述頁面結(jié)構(gòu),然后使用正則表達(dá)式來提取想要的數(shù)據(jù),并定義選擇菜單“menu”,代碼如下所示:
import re def get_all_type_films(self): # 獲取影片類型和類型碼 url = 'https://movie.douban.com/chart' headers = self.get_headers() html = requests.get(url=url, headers=headers).text re_bds = r'<a href=.*?type_name=(.*?)&type=(.*?)&.*?</a>' pattern = re.compile(re_bds, re.S) r_list = pattern.findall(html) # 存放所有類型和對應(yīng)類型碼大字典 type_dict = {} # 定義一個選擇電影類型的菜單 menu = '' # r_list[{'劇情 , 11'},{},..] for r in r_list: type_dict[r[0].strip()] = r[1].strip() # 獲取input的菜單,顯示所有電影類型 menu += r[0].strip() + '|' #返回類型字典以供后續(xù)函數(shù)調(diào)用,并返回輸入菜單menu # {'劇情': '11', '喜劇': '24',...} return type_dict, menu
編寫完整程序
完成上述分析后,下面開始編寫 Python 爬蟲程序,代碼如下:
#coding:utf8 import requests import time import random import re import json from ua_info import ua_list class DoubanSpider(object): def __init__(self): self.url = 'https://movie.douban.com/j/chart/top_list?' self.i = 0 # 獲取隨機(jī)headers def get_headers(self): headers = {'User-Agent':random.choice(ua_list)} return headers # 獲取頁面 def get_page(self,params): # 將json轉(zhuǎn)換為 python 數(shù)據(jù)類型,并返回 html = requests.get(url=self.url,params=params,headers=self.get_headers()).text html=json.loads(html) self.parse_page(html) # 解析并保存數(shù)據(jù) def parse_page(self,html): item = {} # html列表類型: [{電影1},{電影2},{電影3}...] for one in html: # 名稱 + 評分 item['name'] = one['title'].strip() item['score'] = float(one['score'].strip()) print(item) self.i += 1 # 獲取電影總數(shù) def total_number(self,type_number): # F12抓包抓到的地址,type表示電影類型 url = 'https://movie.douban.com/j/chart/top_list_count?type={}&interval_id=100%3A90'.format(type_number) headers = self.get_headers() html = requests.get(url=url,headers=headers).json() total = int(html['total']) return total # 獲取所有電影的類型和對應(yīng)type值 def get_all_type_films(self): # 獲取類型與類型碼 url = 'https://movie.douban.com/chart' headers = self.get_headers() html = requests.get(url=url,headers=headers).text re_bds = r'<a href=.*?type_name=(.*?)&type=(.*?)&.*?</a>' pattern = re.compile(re_bds,re.S) r_list = pattern.findall(html) # 存放所有類型和對應(yīng)類型碼大字典 type_dict = {} #定義一個選擇電影類型的菜單 menu = '' for r in r_list: type_dict[r[0].strip()] = r[1].strip() # 獲取input的菜單,顯示所有電影類型 menu += r[0].strip() + '|' return type_dict,menu # 主程序入口函數(shù) def main(self): # 獲取type的值 type_dict,menu = self.get_all_type_films() menu = menu + '\n你想了解什么類型電影:' name = input(menu) type_number = type_dict[name] # 獲取電影總數(shù) total = self.total_number(type_number) for start in range(0,(total+1),20): #構(gòu)建查詢參數(shù) params = { 'type' : type_number, 'interval_id' : '100:90', 'action' : '', 'start' : str(start), 'limit' : '20' } # 調(diào)用函數(shù),傳遞params參數(shù) self.get_page(params) # 隨機(jī)休眠1-3秒 time.sleep(random.randint(1,3)) print('電影總數(shù)量:%d部'%self.i ) if __name__ == '__main__': spider = DoubanSpider() spider.main()
最后
以上就是使用python爬蟲實(shí)現(xiàn)抓取動態(tài)加載數(shù)據(jù)的詳細(xì)內(nèi)容,更多關(guān)于python抓取動態(tài)加載數(shù)據(jù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解selenium + chromedriver 被反爬的解決方法
這篇文章主要介紹了詳解selenium + chromedriver 被反爬的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10關(guān)于python 讀取csv最快的Datatable的用法,你都學(xué)會了嗎
大家都知道Datatable與眾不同就是快,還有一點(diǎn)大家需要注意使用Datatable庫需要python3.6及以上版本,接下來通過本文給大家介紹了python 讀取csv最快的Datatable的用法,需要的朋友可以參考下2021-10-10Python的collections模塊中的OrderedDict有序字典
字典是無序的,但是collections的OrderedDict類為我們提供了一個有序的字典結(jié)構(gòu),名副其實(shí)的Ordered+Dict,下面通過兩個例子來簡單了解下Python的collections模塊中的OrderedDict有序字典:2016-07-07打包FlaskAdmin程序時(shí)關(guān)于static路徑問題的解決
近期寫了個基于Flask-admin的數(shù)據(jù)庫管理程序,通過pyinstaller打包,給別人用,經(jīng)過幾次嘗試,打包的數(shù)據(jù)一直找不到static里面的樣式文件,查閱資料后,最總把問題搞定了。寫下處理流程,供后來人參考2021-09-09Flask框架利用Echarts實(shí)現(xiàn)繪制圖形
echarts是百度推出的一款開源的基于JavaScript的可視化圖表庫,該開發(fā)庫目前發(fā)展非常不錯,且支持各類圖形的繪制可定制程度高。如下演示案例中,將分別展示運(yùn)用該繪圖庫如何前后端交互繪制(餅狀圖,柱狀圖,折線圖)這三種最基本的圖形,需要的可以參考一下2022-10-10爬蟲代理池Python3WebSpider源代碼測試過程解析
這篇文章主要介紹了爬蟲代理池Python3WebSpider源代碼測試過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12Python批量創(chuàng)建迅雷任務(wù)及創(chuàng)建多個文件
其實(shí)不是真的創(chuàng)建了批量任務(wù),而是用python創(chuàng)建一個文本文件,每行一個要下載的鏈接,然后打開迅雷,復(fù)制文本文件的內(nèi)容,迅雷監(jiān)測到剪切板變化,彈出下載全部鏈接的對話框2016-02-02