天天看點

python 下載下傳 圖檔、音樂、視訊 和 斷點續傳python下載下傳檔案的三種方法使用requests子產品顯示下載下傳進度 進度條類的實作python編寫斷點續傳下載下傳軟體多線程下載下傳檔案Python下載下傳圖檔、音樂、視訊

當然你也可以利用ftplib從ftp站點下載下傳檔案。此外python還提供了另外一種方法requests。

下面來看看三種方法是如何來下載下傳zip檔案的:

方法一:

1.urlopen()方法

urllib.urlopen(url[, data[, proxies]]) :建立一個表示遠端url的類檔案對象,然後像本地檔案一樣操作這個類檔案對象來擷取遠端資料。

參數url表示遠端資料的路徑,一般是網址;

參數data表示以post方式送出到url的資料(玩過web的人應該知道送出資料的兩種方式:post與get。如果你不清楚,也不必太在意,一般情況下很少用到這個參數);

參數proxies用于設定代理。

urlopen傳回 一個類檔案對象,它提供了如下方法:

read() , readline() , readlines() , fileno() , close() :這些方法的使用方式與檔案對象完全一樣;

info():傳回一個httplib.httpmessage 對象,表示遠端伺服器傳回的頭資訊

getcode():傳回http狀态碼。如果是http請求,200表示請求成功完成;404表示網址未找到;

geturl():傳回請求的url;

urllib子產品urlretrieve方法

下面我們再來看看 urllib 子產品提供的 urlretrieve() 函數。urlretrieve() 方法直接将遠端資料下載下傳到本地。

urllib.urlretrieve(url[, filename[, reporthook[, data]]])

參數說明:

url:外部或者本地url

filename:指定了儲存到本地的路徑(如果未指定該參數,urllib會生成一個臨時檔案來儲存資料);

reporthook:是一個回調函數,當連接配接上伺服器、以及相應的資料塊傳輸完畢的時候會觸發該回調。我們可以利用這個回調函數來顯示目前的下載下傳進度。

data:指post到伺服器的資料。該方法傳回一個包含兩個元素的元組(filename, headers),filename表示儲存到本地的路徑,header表示伺服器的響應頭。

方法二:

方法三:

看起來使用urllib最為簡單,一句語句即可。當然你可以把urllib2縮寫成:

請求關鍵參數:stream=true。預設情況下,當你進行網絡請求後,響應體會立即被下載下傳。你可以通過 stream 參數覆寫這個行為,推遲下載下傳響應體直到通路 response.content 屬性。

此時僅有響應頭被下載下傳下來了,連接配接保持打開狀态,是以允許我們根據條件擷取内容:

進一步使用 response.iter_content 和 response.iter_lines 方法來控制工作流,或者以 response.raw 從底層urllib3的 urllib3.httpresponse

保持活動狀态(持久連接配接) 

歸功于urllib3,同一會話内的持久連接配接是完全自動處理的,同一會話内發出的任何請求都會自動複用恰當的連接配接!

注意:隻有當響應體的所有資料被讀取完畢時,連接配接才會被釋放到連接配接池;是以確定将 stream 設定為 false 或讀取 response 對象的 content 屬性。

在python3中,print()方法的預設結束符(end=’\n’),當調用完之後,光标自動切換到下一行,此時就不能更新原有輸出。

将結束符改為“\r”,輸出完成之後,光标會回到行首,并不換行。此時再次調用print()方法,就會更新這一行輸出了。

結束符也可以使用“\d”,為倒退符,光标回退一格,可以使用多個,按需求回退。

在結束這一行輸出時,将結束符改回“\n”或者不指定使用預設

下面是一個格式化的進度條顯示子產品。代碼如下:

另一種方法是調用 curl 之類支援斷點續傳的下載下傳工具。後續補充

一、http斷點續傳原理

其實http斷點續傳原理比較簡單,在http資料包中,可以增加range頭,這個頭以位元組為機關指定請求的範圍,來下載下傳範圍内的位元組流。如:

python 下載下傳 圖檔、音樂、視訊 和 斷點續傳python下載下傳檔案的三種方法使用requests子產品顯示下載下傳進度 進度條類的實作python編寫斷點續傳下載下傳軟體多線程下載下傳檔案Python下載下傳圖檔、音樂、視訊

如上圖勾下來的地方,我們發送資料包時標明請求的内容的範圍,傳回包即獲得相應長度的内容。是以,我們在下載下傳的時候,可以将目标檔案分成很多“小塊”,每次下載下傳一小塊(用range标明小塊的範圍),直到把所有小塊下載下傳完。

當網絡中斷,或出錯導緻下載下傳終止時,我們隻需要記錄下已經下載下傳了哪些“小塊”,還沒有下載下傳哪些。下次下載下傳的時候在range處填寫未下載下傳的小塊的範圍即可,這樣就能構成一個斷點續傳。

其實像迅雷這種多線程下載下傳器也是同樣的原理。将目标檔案分成一些小塊,再配置設定給不同線程去下載下傳,最後整合再檢查完整性即可。

二、python下載下傳檔案實作方式

我們仍然使用之前介紹過的requests庫作為http請求庫。

是以,如果要下載下傳大檔案的話,就将steam設定為true,慢慢下載下傳,而不是等整個檔案下載下傳完才傳回。

stackoverflow上有同學給出了一個簡單的下載下傳demo:

這基本上就是我們核心的下載下傳代碼了。

當使用requests的get下載下傳大檔案/資料時,建議使用使用stream模式。

當把get函數的stream參數設定成false時,它會立即開始下載下傳檔案并放到記憶體中,如果檔案過大,有可能導緻記憶體不足。

當把get函數的stream參數設定成true時,它不會立即開始下載下傳,當你使用iter_content或iter_lines周遊内容或通路内容屬性時才開始下載下傳。需要注意一點:檔案沒有下載下傳之前,它也需要保持連接配接。

iter_content:一塊一塊的周遊要下載下傳的内容

iter_lines:一行一行的周遊要下載下傳的内容

使用上面兩個函數下載下傳大檔案可以防止占用過多的記憶體,因為每次隻下載下傳小部分資料。

三、斷點續傳結合大檔案下載下傳

好,我們結合這兩個知識點寫個小程式:支援斷點續傳的下載下傳器。

我們可以先考慮一下需要注意的有哪些點,或者可以添加的功能有哪些:

其實想一下還是有很多疑慮,而且有些地方可能一時還解決不了。先大概想一下各個問題的答案:

解決了這些疑問,我們就開始動筆了。實際上,疑問并不是在未動筆的時候幹想出來的,基本都是我寫了一半突然發現的問題。

這是下載下傳的方法。首先if語句調用self.support_continue(url)判斷是否支援斷點續傳。如果支援則從一個臨時檔案中讀取目前已經下載下傳了多少位元組,如果不存在這個檔案則會抛出錯誤,那麼size預設=0,說明一個位元組都沒有下載下傳。

然後就請求url,獲得下載下傳連接配接,for循環下載下傳。這個時候我們得抓住異常,一旦出現異常,不能讓程式退出,而是正常将目前已下載下傳位元組size寫入臨時檔案中。下次再次下載下傳的時候讀取這個檔案,将range設定成bytes=(size+1)-,也就是從目前位元組的後一個位元組開始到結束的範圍。從這個範圍開始下載下傳,來實作一個斷點續傳。

判斷是否支援斷點續傳的方法還兼顧了一個獲得目标檔案大小的功能:

用正則比對出大小,獲得直接擷取headers['content-length'],獲得将其設定為0.

運作來擷取一下emlog最新的安裝包:

python 下載下傳 圖檔、音樂、視訊 和 斷點續傳python下載下傳檔案的三種方法使用requests子產品顯示下載下傳進度 進度條類的實作python編寫斷點續傳下載下傳軟體多線程下載下傳檔案Python下載下傳圖檔、音樂、視訊

中間我按contrl + c人工打斷了下載下傳程序,但之後還是繼續下載下傳,實作了“斷點續傳”。但在我實際測試過程中,并不是那麼多請求可以斷點續傳的,是以我對于不支援斷點續傳的檔案這樣處理:重新下載下傳。

下載下傳後的壓縮包正常解壓,也充分證明了下載下傳的完整性:

python 下載下傳 圖檔、音樂、視訊 和 斷點續傳python下載下傳檔案的三種方法使用requests子產品顯示下載下傳進度 進度條類的實作python編寫斷點續傳下載下傳軟體多線程下載下傳檔案Python下載下傳圖檔、音樂、視訊

動态圖示範

python 下載下傳 圖檔、音樂、視訊 和 斷點續傳python下載下傳檔案的三種方法使用requests子產品顯示下載下傳進度 進度條類的實作python編寫斷點續傳下載下傳軟體多線程下載下傳檔案Python下載下傳圖檔、音樂、視訊

下載下傳視訊的效果

python 下載下傳 圖檔、音樂、視訊 和 斷點續傳python下載下傳檔案的三種方法使用requests子產品顯示下載下傳進度 進度條類的實作python編寫斷點續傳下載下傳軟體多線程下載下傳檔案Python下載下傳圖檔、音樂、視訊