原文地址https://blog.csdn.net/u011541946/article/details/77700074
前面一篇文章介紹了response對象的一些常用API,也已經提到,我們的重點是對response對象的操作。主要的操作就是數據分析和提取,一般來說,數據有很多種,有字段,有圖片,有視頻,有音頻,凡是html頁面能支持的content-type都是數據。只是不同場景下,有不同目的。例如,加入你需要在一個圖片網站,爬取一些你敢興趣的圖片。或者你需要在一些招聘網站爬取職位信息,或者,你需要從服務器端下載一個文件。這些事情requests都可以幫你做到。本文,就是簡單介紹,如何從網頁獲取一個圖片的過程。
1. 設置我們的場景
打開百度圖片搜索,輸入selenium,然后找到一個selenium的圖片,我們需要把這個圖片通過requests下載到本地,圖片如下。
這里我們假如說要下載第一張圖片。
2. 手動獲取圖片在服務器上的url
點擊打開上面紅圈這個圖片,記錄下這個圖片在服務器上的路徑。你可以右鍵這個圖片-查看圖片,獲取到這個路徑:https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1504662907&di=2bf9d214dfdc9b0243163fb0a20f1228&imgtype=jpg&er=1&src=http%3A%2F%2Fpic.baike.soso.com%2Fp%2F20140415%2Fbki-20140415104220-671149140.jpg
3. 利用requests.get()方法和response.content方法是否能夠打印出圖片
import requests def download_image(): url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1504068152047&di=8b53bf6b8e5deb64c8ac726e260091aa&imgtype=0&src=http%3A%2F%2Fpic.baike.soso.com%2Fp%2F20140415%2Fbki-20140415104220-671149140.jpg' response = requests.get(url) print(response.status_code) print(response.content) if __name__ == '__main__': download_image()
運行一下,發現請求正確,但是用response.content打印出來是一堆亂碼。
200 OK
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00H\x00H\x00\x00\xff\xd....后面跟着很多類似的亂碼一樣的數據
現在問題來了,我們怎么樣才能把圖片下載到本地,用response.content方法是行不通的。我們知道,圖片也是文件格式,圖片也是一些二進制代碼組成。我們把圖片當做普通的文件,然后通過字節流的方法,把圖片保存到本地。
4.通過字節流方式保存圖片
大概的原理是,一個圖片是由字節流數據組成,我們可以把圖片分層多個字節流數據,加載到內存,然后復制字節流到一個本地路徑,最后組合成一張圖片。
import requests def download_image(): url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1504068152047&di=8b53bf6b8e5deb64c8ac726e260091aa&imgtype=0&src=http%3A%2F%2Fpic.baike.soso.com%2Fp%2F20140415%2Fbki-20140415104220-671149140.jpg' response = requests.get(url, stream = True) # 這里打開一個空的png文件,相當於創建一個空的txt文件,wb表示寫文件 with open('selenium.png', 'wb') as file: # 每128個流遍歷一次 for data in response.iter_content(128): # 把流寫入到文件,這個文件最后寫入完成就是,selenium.png file.write(data) # data相當於一塊一塊數據寫入到我們的圖片文件中 print(response.status_code) if __name__ == '__main__': download_image()
運行之后,得到請求狀態碼是200,而且會在當前這個腳本文件同級目錄下生成一個selenium.png的圖片。如果你要指定圖片保存路徑,你可以在open('圖片完整路徑','wb'),通過這樣方式,把圖片保存到你想要保存的磁盤路徑。上面雖然實現了我們的下載圖片的目的,但是有一個問題就是,我們使用完了stream之后,沒有立馬去關閉,這樣會造成內存資源緊張,如果是批量下載很多圖片,這個方式是不可取的。
5.換一種方式,及時關閉stream
import requests from contextlib import closing def download_image_improve(): url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1504068152047&di=8b53bf6b8e5deb64c8ac726e260091aa&imgtype=0&src=http%3A%2F%2Fpic.baike.soso.com%2Fp%2F20140415%2Fbki-20140415104220-671149140.jpg' response = requests.get(url, stream = True) with closing(requests.get(url, stream = True)) as response: # 這里打開一個空的png文件,相當於創建一個空的txt文件,wb表示寫文件 with open('selenium1.png', 'wb') as file: # 每128個流遍歷一次 for data in response.iter_content(128): # 把流寫入到文件,這個文件最后寫入完成就是,selenium.png file.write(data) if __name__ == '__main__': download_image_improve()
運行之后,也會在當前腳本文件所在目錄生成一個selenium1.png文件。contextlib.closing()函數是實現在一個代碼塊之后自動關閉,這里的代碼塊,就是我們請求下載圖片的過程。這篇,已經實現了限定的圖片url下載,如果是爬蟲,肯定是大量圖片下載。上面圖片下載可以提取出來,重構成一個方法,在實際爬蟲中調用。當然,爬蟲中,很多是變量,圖片請求url是變量,圖片名稱和保存路徑也是變量。這里不繼續討論,爬蟲實現的過程了。