requests庫之文件下載


方法一:

使用 urllib 模塊提供的 urlretrieve() 函數。urlretrieve() 方法直接將遠程數據下載到本地

urlretrieve(url, [filename=None, [reporthook=None, [data=None]]])
  • 請求url不可為空: urlretrieve(url) 
  • 下載后的文件保存路徑可為空: urlretrieve(url, [filename=None]) 
  • 傳輸到服務器的數據data可為空: urlretrieve(url, [filename=None, [reporthook=None, [data=None]]]) 

說明:

  • 參數 finename 指定了保存本地路徑(如果參數未指定,urllib會生成一個臨時文件保存數據。)

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

  • 參數 data 指 post 到服務器的數據,該方法返回一個包含兩個元素的(filename, headers)元組,filename 表示保存到本地的路徑,header 表示服務器的響應頭。 

實例:

from urllib import request

load_url = 'http://docs.python-requests.org/zh_CN/latest/_static/requests-sidebar.png'


def Schedule(a,b,c):
    '''
    a:已經下載的數據塊
    b:數據塊的大小
    c:遠程文件的大小
   '''
    per = 100.0 * a * b / c
    if per > 100 :
        per = 100
    print('%.2f%%' % per)


request.urlretrieve(url=load_url,filename='d:\\python.png',reporthook=Schedule)

方法二:

使用requests模塊

使用該方法下載大文件可以防止占用過多的內存,因為每次只下載小部分數據。

import requests

load_url = 'http://docs.python-requests.org/zh_CN/latest/_static/requests-sidebar.png'

r = requests.get(url=load_url,stream=True)
with open("D:\\python.png","wb") as f:
    for chunk in r.iter_content(chunk_size=1024):
        f.write(chunk)
  • stream參數默認為False,它會立即開始下載文件並放到內存中,如果文件過大,有可能導致內存不足。

  • stream參數設置成True時,它不會立即開始下載,當你使用iter_content或iter_lines遍歷內容訪問內容屬性時才開始下載。

  • iter_content:一塊一塊的遍歷要下載的內容

  • iter_lines:一行一行的遍歷要下載的內容

關於requests請求時的stream參數詳解:

默認情況下,當你進行網絡請求后,響應體會立即被下載。(當響應體數據量過大時,立即下載會占用系統大量內存)【當響應體數據量並不是很大時,可以不用考慮內存,即可以直接下載】

你可以通過 stream 參數覆蓋這個行為,推遲下載響應體直到訪問 Response.content 屬性:(請求后不立即下載響應體,而是先下載響應頭)【當訪問r.content字節碼的時候才會下載響應體】

tarball_url = 'https://github.com/kennethreitz/requests/tarball/master'
r = requests.get(tarball_url, stream=True)

此時僅有響應頭被下載下來了,連接保持打開狀態,因此允許我們根據條件獲取內容:

if int(r.headers['content-length']) < TOO_LONG:
  content = r.content # 此時開始下載響應體
  ...

解釋:

歸功於 urllib3,同一會話內的持久連接是完全自動處理的!同一會話內你發出的任何請求都會自動復用恰當的連接。

只有所有的響應體數據被讀取完畢連接才會被釋放為連接池;以下是釋放連接池的兩種情況:

  1. 所以當requests請求時設置的參數stream為False時【requests請求時,stream默認為False】,所有的響應體數據被讀取完之后立即釋放連接池。
  2. 或者當requests請求時設置的參數stream為True時,當訪問r.content屬性且讀取下載響應體數據之后也會立即釋放連接池。

當然:如果你在請求中把  stream  設為 True 的時候,且不訪問任何方法,那么Requests 無法將連接釋放回連接池,除非你消耗了所有的數據,或者調用了  Response.close 。 否則這樣會帶來連接效率低下的問題。

關於Response.iter_content的詳解

Response.iter_content是可迭代對象。

一塊一塊的遍歷要下載的內容【可以理解為一塊一塊的下載服務器返回的數據量過大的響應體數據】,然后通過對文件流的操作按塊逐一寫入指定的路徑文件中。

在請求中設置stream = True時,可以避免將內容一次性讀入內存以獲得較大的響應。塊大小是它應該循環每次讀入內存的字節數【即chunk_size=1024]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM