Python 下載文件的多種方法

文 |?某某白米飯
來源:Python 技術(shù)「ID: pythonall」

本文檔介紹了 Python 下載文件的各種方式,從下載簡單的小文件到用斷點續(xù)傳的方式下載大文件。
Requests
使用 Requests 模塊的 get 方法從一個 url 上下載文件,在 python 爬蟲中經(jīng)常使用它下載簡單的網(wǎng)頁內(nèi)容
import?requests
#?圖片來自bing.com
url?=?'https://cn.bing.com/th?id=OHR.DerwentIsle_EN-CN8738104578_400x240.jpg'
def?requests_download():
????content?=?requests.get(url).content
????with?open('pic_requests.jpg',?'wb')?as?file:
????????file.write(content)
urllib
使用 python 內(nèi)置的 urllib 模塊的 urlretrieve 方法直接將 url 請求保存成文件
from?urllib?import?request
#?圖片來自bing.com
url?=?'https://cn.bing.com/th?id=OHR.DerwentIsle_EN-CN8738104578_400x240.jpg'
def?urllib_download():
????request.urlretrieve(url,?'pic_urllib.jpg')
urllib3
urllib3 是一個用于 Http 客戶端的 Python 模塊,它使用連接池對網(wǎng)絡(luò)進行請求訪問
def?urllib3_download():
????#?創(chuàng)建一個連接池
????poolManager?=?urllib3.PoolManager()
????resp?=?poolManager.request('GET',?url)
????with?open("pic_urllib3.jpg",?"wb")?as?file:
????????file.write(resp.data)
????resp.release_conn()
wget
在 Linux 系統(tǒng)中有 wget 命令,可以方便的下載網(wǎng)上的資源,Python 中也有相應(yīng)的 wget 模塊。使用 pip install 命令安裝
import?wget
#?圖片來自bing.com
url?=?'https://cn.bing.com/th?id=OHR.DerwentIsle_EN-CN8738104578_400x240.jpg'
def?wget_download():
????wget.download(url,?out='pic_wget.jpg')
也可以直接在命令行中使用 wget 命令
python?-m?wget?https://cn.bing.com/th?id=OHR.DerwentIsle_EN-CN8738104578_400x240.jpg
分塊下載大文件
在需要下載的文件非常大,電腦的內(nèi)存空間完全不夠用的情況下,可以使用 requests 模塊的流模式,默認情況下 stream 參數(shù)為 False, 文件過大會導(dǎo)致內(nèi)存不足。stream 參數(shù)為 True 的時候 requests 并不會立刻開始下載,只有在調(diào)用 iter_content 或者 iter_lines 遍歷內(nèi)容時下載
iter_content:一塊一塊的遍歷要下載的內(nèi)容 iter_lines:一行一行的遍歷要下載的內(nèi)容
import?requests
def?steam_download():
????#?vscode?客戶端
????url?=?'https://vscode.cdn.azure.cn/stable/e5a624b788d92b8d34d1392e4c4d9789406efe8f/VSCodeUserSetup-x64-1.51.1.exe'
????with?requests.get(url,?stream=True)?as?r:
????????with?open('vscode.exe',?'wb')?as?flie:
????????????#?chunk_size?指定寫入大小每次寫入?1024?*?1024?bytes
????????????for?chunk?in?r.iter_content(chunk_size=1024*1024):
????????????????if?chunk:
????????????????????flie.write(chunk)
進度條
在下載大文件的時候加上進度條美化下載界面,可以實時知道下載的網(wǎng)絡(luò)速度和已經(jīng)下載的文件大小,這里使用 tqdm 模塊作為進度條顯示,可以使用 pip install tqdm 安裝
from?tqdm?import?tqdm
def?tqdm_download():
????url?=?'https://vscode.cdn.azure.cn/stable/e5a624b788d92b8d34d1392e4c4d9789406efe8f/VSCodeUserSetup-x64-1.51.1.exe'
????resp?=?requests.get(url,?stream=True)
????#?獲取文件大小
????file_size?=?int(resp.headers['content-length'])
????
????with?tqdm(total=file_size,?unit='B',?unit_scale=True,?unit_divisor=1024,?ascii=True,?desc='vscode.exe')?as?bar:
????????with?requests.get(url,?stream=True)?as?r:
????????????with?open('vscode.exe',?'wb')?as?fp:
????????????????for?chunk?in?r.iter_content(chunk_size=512):
????????????????????if?chunk:
????????????????????????fp.write(chunk)
????????????????????????bar.update(len(chunk))
tqdm 參數(shù)說明:
total:bytes,整個文件的大小 unit='B': 按 bytes 為單位計算 unit_scale=True:以 M 為單位顯示速度 unit_divisor=1024:文件大小和速度按 1024 除以,默認時按 1000 來除 ascii=True:進度條的顯示符號,用于兼容 windows 系統(tǒng) desc='vscode.exe' 進度條前面的文件名
示例結(jié)果

斷點續(xù)傳
HTTP/1.1 在協(xié)議的請求頭中增加了一個名為 Range的字段域, Range 字段域讓文件從已經(jīng)下載的內(nèi)容開始繼續(xù)下載
如果網(wǎng)站支持 Range 字段域請求響應(yīng)的狀態(tài)碼為 206(Partial Content),否則為 416(Requested Range not satisfiable)
Range 的格式
Range:[unit=first byte pos]?-?[last byte pos],即 Range =?開始字節(jié)位置-結(jié)束字節(jié)位置,單位:bytes
將 Range 加入到 headers 中
from?tqdm?import?tqdm
def?duan_download():
????url?=?'https://vscode.cdn.azure.cn/stable/e5a624b788d92b8d34d1392e4c4d9789406efe8f/VSCodeUserSetup-x64-1.51.1.exe'
????r?=?requests.get(url,?stream=True)
????#?獲取文件大小
????file_size?=?int(r.headers['content-length'])
????file_name?=?'vscode.exe'
????#?如果文件存在獲取文件大小,否在從?0?開始下載,
????first_byte?=?0
????if?os.path.exists(file_name):
????????first_byte?=?os.path.getsize(file_name)
????????
????#?判斷是否已經(jīng)下載完成
????if?first_byte?>=?file_size:
????????return
????#?Range?加入請求頭
????header?=?{"Range":?f"bytes={first_byte}-{file_size}"}
????#?加了一個?initial?參數(shù)
????with?tqdm(total=file_size,?unit='B',?initial=first_byte,?unit_scale=True,?unit_divisor=1024,?ascii=True,?desc=file_name)?as?bar:
????????#?加?headers?參數(shù)
????????with?requests.get(url,?headers?=?header,?stream=True)?as?r:
????????????with?open(file_name,?'ab')?as?fp:
????????????????for?chunk?in?r.iter_content(chunk_size=512):
????????????????????if?chunk:
????????????????????????fp.write(chunk)
????????????????????????bar.update(len(chunk))
示例結(jié)果
啟動下載一段時間后,關(guān)閉腳本重新運行,文件在斷開的內(nèi)容后繼續(xù)下載

總結(jié)
本文介紹了常用的 7 中文件下載方式,其他的下載方式大家可以在留言區(qū)交流交流共同進步
PS:公號內(nèi)回復(fù)「Python」即可進入Python 新手學(xué)習(xí)交流群,一起 100 天計劃!
老規(guī)矩,兄弟們還記得么,右下角的 “在看” 點一下,如果感覺文章內(nèi)容不錯的話,記得分享朋友圈讓更多的人知道!


【代碼獲取方式】
