本節中,咱們以今日頭條爲例來嘗試經過分析Ajax請求來抓取網頁數據的方法。此次要抓取的目標是今日頭條的街拍美圖,抓取完成以後,將每組圖片分文件夾下載到本地並保存下來。git
在本節開始以前,請確保已經安裝好requests庫。github
首先,實現方法get_page()
來加載單個Ajax請求的結果。其中惟一變化的參數就是offset
,因此咱們將它看成參數傳遞,實現以下:json
import requests from urllib.parse import urlencode def get_page(offset): params = { 'offset': offset, 'format': 'json', 'keyword': '街拍', 'autoload': 'true', 'count': '20', 'cur_tab': '1', } url = 'http://www.toutiao.com/search_content/?' + urlencode(params) try: response = requests.get(url) if response.status_code == 200: return response.json() except requests.ConnectionError: return None
這裏咱們用urlencode()
方法構造請求的GET參數,而後用requests請求這個連接,若是返回狀態碼爲200,則調用response
的json()
方法將結果轉爲JSON格式,而後返回。數組
接下來,再實現一個解析方法:提取每條數據的image_detail
字段中的每一張圖片連接,將圖片連接和圖片所屬的標題一併返回,此時能夠構造一個生成器。實現代碼以下:多線程
def get_images(json): if json.get('data'): for item in json.get('data'): title = item.get('title') images = item.get('image_detail') for image in images: yield { 'image': image.get('url'), 'title': title }
接下來,實現一個保存圖片的方法save_image()
,其中item
就是前面get_images()
方法返回的一個字典。在該方法中,首先根據item
的title
來建立文件夾,而後請求這個圖片連接,獲取圖片的二進制數據,以二進制的形式寫入文件。圖片的名稱可使用其內容的MD5值,這樣能夠去除重複。相關代碼以下:ide
import os from hashlib import md5 def save_image(item): if not os.path.exists(item.get('title')): os.mkdir(item.get('title')) try: response = requests.get(item.get('image')) if response.status_code == 200: file_path = '{0}/{1}.{2}'.format(item.get('title'), md5(response.content).hexdigest(), 'jpg') if not os.path.exists(file_path): with open(file_path, 'wb') as f: f.write(response.content) else: print('Already Downloaded', file_path) except requests.ConnectionError: print('Failed to Save Image')
最後,只須要構造一個offset
數組,遍歷offset
,提取圖片連接,並將其下載便可:url
from multiprocessing.pool import Pool def main(offset): json = get_page(offset) for item in get_images(json): print(item) save_image(item) GROUP_START = 1 GROUP_END = 20 if __name__ == '__main__': pool = Pool() groups = ([x * 20 for x in range(GROUP_START, GROUP_END + 1)]) pool.map(main, groups) pool.close() pool.join()
這裏定義了分頁的起始頁數和終止頁數,分別爲GROUP_START
和GROUP_END
,還利用了多線程的線程池,調用其map()
方法實現多線程下載。spa
這樣整個程序就完成了,運行以後能夠發現街拍美圖都分文件夾保存下來了,如圖所示。線程
最後,咱們給出本節的代碼地址:https://github.com/Python3WebSpider/Jiepai。code