python3 學習 3:python爬蟲之爬取動態載入的圖片,以百度圖片為例
轉: https://blog.csdn.net/qq_32166627/article/details/60882964
前言:
前面我們爬取圖片的網站都是靜態的,在頁面中右鍵檢視原始碼就能看到網頁中圖片的位置。這樣我們用requests庫得到頁面原始碼後,再用bs4庫解析標籤即可儲存圖片到本地。
當我們在看百度圖片時,右鍵–檢查–Elements,點選箭頭,再用箭頭點選圖片時,會顯示圖片的位置和樣式。但是,當我們右鍵檢視網頁原始碼時,出來的卻是一大堆JavaScript程式碼,並沒有圖片的連結等資訊。這是為什麼呢?
這是因為,百度圖片的網頁是一個動態頁面,它的網頁原始資料其實是沒有這個圖片的,通過執行JavaScript,把這個圖片資料把它插入到網頁的html標籤裡面,那這樣造成的結果是,我們在開發者工具中雖然能看到這個html標籤,但實際上,當我們在看網頁的原始資料的時候,其實是沒有這個標籤的,它只在執行時載入和渲染,那這個時候怎麼辦呢?怎麼把這個圖片給下載下來呢?這裡面我們就換一個思路,我們就來抓包。
我們點選Network–XHR,然後我們在往下滑動滾動條時,會一直出現一個名為:acjson?tn=resultjson&ipn=…的請求,點選它再點Preview,我們看到這是一條json資料,點開data,我們看到這裡面有30條資料,每一條都對應著一張圖片。
於是我們就清楚了,百度圖片一開始只加載30張圖片,當我們往下滑動滾動條時,頁面會動態載入1條json資料,每條json資料裡面包含了30條資訊,資訊裡面又包含了圖片的URL,JavaScript會將這些url解析並顯示出來。這樣,每次滾動到底就又多出30張圖片。
那麼,這些一直出現的json資料有什麼規律呢?我們點選Headers,然後對比這些json資料的頭部資訊。通過對比,我們發現headers下的Query String Parameters中的欄位大多保持不變,只有pn欄位保持以30為步長遞增。wonderful!這下找到規律啦!
正文:
既然知道了原理,我們就來寫程式碼實現python爬蟲抓取百度圖片。
二話不說就上程式碼:
import requests import os def getManyPages(keyword,pages): params=[] for i in range(30,30*pages+30,30): params.append({ 'tn': 'resultjson_com', 'ipn': 'rj', 'ct': 201326592, 'is': '', 'fp': 'result', 'queryWord': keyword, 'cl': 2, 'lm': -1, 'ie': 'utf-8', 'oe': 'utf-8', 'adpicid': '', 'st': -1, 'z': '', 'ic': 0, 'word': keyword, 's': '', 'se': '', 'tab': '', 'width': '', 'height': '', 'face': 0, 'istype': 2, 'qc': '', 'nc': 1, 'fr': '', 'pn': i, 'rn': 30, 'gsm': '1e', '1488942260214': '' }) url = 'https://image.baidu.com/search/acjson' urls = [] for i in params: urls.append(requests.get(url,params=i).json().get('data')) return urls def getImg(dataList, localPath): if not os.path.exists(localPath): # 新建資料夾 os.mkdir(localPath) x = 0 for list in dataList: for i in list: if i.get('thumbURL') != None: print('正在下載:%s' % i.get('thumbURL')) ir = requests.get(i.get('thumbURL')) open(localPath + '%d.jpg' % x, 'wb').write(ir.content) x += 1 else: print('圖片連結不存在') if __name__ == '__main__': dataList = getManyPages('36D美女',10) # 引數1:關鍵字,引數2:要下載的頁數 getImg(dataList,'C:/Users/mycomm/Desktop/photo') # 引數2:指定儲存的路徑