requests如何友好地請求下載大檔案?requests實現分段下載、斷點續傳

不離鞘發表於2020-11-25

前言

requests.get()請求一個視訊連線連結,如果視訊太大怎麼辦?
requests.get()下載到一半暫停了,想要接著下載怎麼辦?


requests如何友好地請求下載大檔案?

當我們用requests.get()請求某個連結時,如果是大檔案,比如下載1GB大小的視訊,那該怎麼辦呢?
在get()方法裡面加一個引數stream=True,即:requests.get(url,stream=True)

加 和 不加stream引數的區別:
不加stream引數:
get請求會把所有的資料請求下來,一個視訊1個G的話,會把1G的視訊下載到記憶體裡面,然後再進一步操作。

加stream引數:
get請求會先建立連線,而不會把content內容或text內容下載到記憶體裡,等開始對content操作的時候,get請求這個時候才開始下載資料。

通常還可以這樣分一段一段寫入:

import requests
url = ''
r = requests.get(url,stream=True)
with open('filename', 'wb') as fp:
    for item in r.iter_content(10240):
	    # 10240表示每次會寫入10240個位元組,即10KB
        fp.write(item)

這樣就可以友好地下載大檔案了,對於下載較大的視訊尤其管用。


requests實現斷點續傳

在requests.get()的請求頭headers加上Range欄位就可以實現斷點續傳了。

語法格式如下:

headers = {'Range': 'bytes=%d-%d'%(start,end)}

在%d-%d的位置傳入起始位元組數終止位元組數
例如:

# 從第0個位元組下載到第500個位元組(包括第500個位元組)
headers = {'Range': 'bytes=0-500'}

# 從第501個位元組下載到最後一個位元組
headers = {'Range': 'bytes=501-'}

嘗試用斷點續傳的方式下載一個圖片試試:
找一個圖片連結,該圖片大小為185KB,即185*1024個位元組

先下載前面100KB:

import requests
headers = {'Range': 'bytes=0-%d'%(100*1024)}
url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1606242360113&di=6f1e59e7ad5cae73389a44f65c466242&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201505%2F03%2F20150503152411_JsYLR.jpeg'
r = requests.get(url,headers=headers)
with open('night.jpg', 'wb') as fp:
    fp.write(r.content)

看看只下載了100KB的這張圖片:
在這裡插入圖片描述
接著下載剩下的內容

headers = {'Range': 'bytes=%d-'%(100*1024+1)}
url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1606242360113&di=6f1e59e7ad5cae73389a44f65c466242&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201505%2F03%2F20150503152411_JsYLR.jpeg'
r = requests.get(url,headers=headers)
with open('night.jpg', 'ab') as fp:  # 注意用 'ab'模式開啟檔案
    fp.write(r.content)

完整圖片:
在這裡插入圖片描述
會不會覺得斷點續傳也就那樣?


總結

  • 友好地下載大檔案:requests.get(stream=True)
  • 斷點續傳:在請求頭headers上加入{'Range': 'bytes=%d-%d'}欄位

相關文章