從基礎(chǔ)到進(jìn)階詳解Python下載文件的方法完整指南
在Python中下載文件是一項(xiàng)常見(jiàn)任務(wù),無(wú)論是從網(wǎng)頁(yè)下載圖片、文檔,還是通過(guò)API獲取數(shù)據(jù),掌握文件下載技術(shù)都是開(kāi)發(fā)者的必備技能。本文將系統(tǒng)介紹Python下載文件的多種方法,涵蓋基礎(chǔ)實(shí)現(xiàn)、高級(jí)技巧和常見(jiàn)問(wèn)題解決方案。
一、基礎(chǔ)方法:使用標(biāo)準(zhǔn)庫(kù)下載文件
1. 使用urllib.request(Python內(nèi)置庫(kù))
import urllib.request
url = "https://example.com/file.zip"
filename = "downloaded_file.zip"
try:
urllib.request.urlretrieve(url, filename)
print(f"文件已下載到: {filename}")
except Exception as e:
print(f"下載失敗: {e}")
特點(diǎn):
- 無(wú)需安裝第三方庫(kù)
- 適合簡(jiǎn)單下載場(chǎng)景
- 缺乏進(jìn)度顯示和錯(cuò)誤處理細(xì)節(jié)
2. 使用requests庫(kù)(推薦)
import requests
url = "https://example.com/file.zip"
filename = "downloaded_file.zip"
try:
response = requests.get(url, stream=True) # 使用流式下載大文件
response.raise_for_status() # 檢查請(qǐng)求是否成功
with open(filename, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192): # 分塊寫入
if chunk: # 過(guò)濾掉keep-alive新塊
f.write(chunk)
print(f"文件已下載到: {filename}")
except requests.exceptions.RequestException as e:
print(f"下載失敗: {e}")
優(yōu)勢(shì):
- 更簡(jiǎn)潔的API
- 支持流式下載(適合大文件)
- 完善的錯(cuò)誤處理機(jī)制
- 可添加請(qǐng)求頭、代理等高級(jí)功能
二、進(jìn)階技巧:增強(qiáng)下載功能
1. 顯示下載進(jìn)度
import requests
from tqdm import tqdm # 需要安裝: pip install tqdm
url = "https://example.com/large_file.zip"
filename = "large_file.zip"
try:
response = requests.get(url, stream=True)
total_size = int(response.headers.get('content-length', 0))
with open(filename, 'wb') as f, tqdm(
desc=filename,
total=total_size,
unit='iB',
unit_scale=True,
unit_divisor=1024,
) as bar:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
bar.update(len(chunk))
print("\n下載完成!")
except Exception as e:
print(f"下載失敗: {e}")
2. 斷點(diǎn)續(xù)傳功能
import os
import requests
url = "https://example.com/large_file.zip"
filename = "large_file.zip"
# 檢查是否已部分下載
downloaded_size = 0
if os.path.exists(filename):
downloaded_size = os.path.getsize(filename)
headers = {'Range': f'bytes={downloaded_size}-'}
try:
response = requests.get(url, headers=headers, stream=True)
response.raise_for_status()
with open(filename, 'ab') as f: # 以追加模式打開(kāi)
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
print("下載完成!")
except Exception as e:
print(f"下載失敗: {e}")
3. 多線程/異步下載(加速下載)
import requests
from concurrent.futures import ThreadPoolExecutor
import os
def download_chunk(url, start, end, filename, chunk_num):
headers = {'Range': f'bytes={start}-{end}'}
try:
response = requests.get(url, headers=headers, stream=True)
with open(f"{filename}.part{chunk_num}", 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
return True
except Exception as e:
print(f"分塊{chunk_num}下載失敗: {e}")
return False
def merge_files(filename, num_chunks):
with open(filename, 'wb') as outfile:
for i in range(num_chunks):
part_filename = f"{filename}.part{i}"
if os.path.exists(part_filename):
with open(part_filename, 'rb') as infile:
outfile.write(infile.read())
os.remove(part_filename)
url = "https://example.com/very_large_file.zip"
filename = "very_large_file.zip"
file_size = 1024 * 1024 * 100 # 假設(shè)文件100MB
chunk_size = 1024 * 1024 * 10 # 每塊10MB
num_chunks = file_size // chunk_size
# 創(chuàng)建線程池下載各分塊
with ThreadPoolExecutor(max_workers=5) as executor:
futures = []
for i in range(num_chunks):
start = i * chunk_size
end = start + chunk_size - 1 if i != num_chunks - 1 else file_size - 1
futures.append(executor.submit(
download_chunk, url, start, end, filename, i
))
# 等待所有分塊下載完成
for future in futures:
future.result()
# 合并分塊
merge_files(filename, num_chunks)
print("下載并合并完成!")
三、常見(jiàn)場(chǎng)景解決方案
1. 下載網(wǎng)頁(yè)上的所有資源
import requests
from bs4 import BeautifulSoup
import os
def download_resources(url, output_folder="downloads"):
os.makedirs(output_folder, exist_ok=True)
try:
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# 下載圖片
for img in soup.find_all('img'):
img_url = img.get('src')
if img_url and not img_url.startswith('data:'):
if not img_url.startswith(('http://', 'https://')):
img_url = f"{url}/{img_url}" if not url.endswith('/') else f"{url}{img_url}"
try:
img_data = requests.get(img_url).content
img_name = os.path.join(output_folder, img_url.split('/')[-1])
with open(img_name, 'wb') as f:
f.write(img_data)
except Exception as e:
print(f"圖片下載失敗: {e}")
# 可以類似地下載CSS/JS等資源
print("資源下載完成!")
except Exception as e:
print(f"網(wǎng)頁(yè)下載失敗: {e}")
download_resources("https://example.com")
2. 使用代理下載
import requests
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
}
url = "https://example.com"
try:
response = requests.get(url, proxies=proxies)
with open("page.html", 'w', encoding='utf-8') as f:
f.write(response.text)
print("通過(guò)代理下載成功!")
except Exception as e:
print(f"代理下載失敗: {e}")
3. 處理下載重定向
import requests
url = "http://example.com/redirecting_link"
try:
response = requests.get(url, allow_redirects=True) # 默認(rèn)允許重定向
final_url = response.url # 獲取最終URL
print(f"最終URL: {final_url}")
# 下載最終文件
with open("final_file.txt", 'wb') as f:
f.write(response.content)
except Exception as e:
print(f"下載失敗: {e}")
四、最佳實(shí)踐與注意事項(xiàng)
- 錯(cuò)誤處理:始終添加異常處理,特別是網(wǎng)絡(luò)請(qǐng)求可能因各種原因失敗
- 資源清理:使用
with語(yǔ)句確保文件正確關(guān)閉 - 大文件處理:使用流式下載(
stream=True)和分塊寫入 - 安全性:
- 驗(yàn)證SSL證書(shū)(默認(rèn)行為)
- 對(duì)用戶提供的URL進(jìn)行驗(yàn)證
- 限制文件類型和保存路徑
- 性能優(yōu)化:
- 合理設(shè)置分塊大?。ㄍǔ?KB-1MB)
- 多線程下載適合高延遲網(wǎng)絡(luò)
- 考慮使用異步IO(如
aiohttp)提高并發(fā)性能
五、完整示例:帶進(jìn)度條的下載函數(shù)
import requests
from tqdm import tqdm
import os
def download_file(url, filename=None, chunk_size=8192):
"""
下載文件并顯示進(jìn)度條
:param url: 文件URL
:param filename: 保存文件名(可選,默認(rèn)從URL提?。?
:param chunk_size: 分塊大小(字節(jié))
:return: 保存的文件路徑
"""
try:
# 獲取文件名(如果未提供)
if filename is None:
filename = os.path.basename(url.split('?')[0]) # 去除查詢參數(shù)
# 發(fā)送請(qǐng)求
response = requests.get(url, stream=True)
response.raise_for_status()
# 獲取總大?。ㄈ绻?wù)器提供)
total_size = int(response.headers.get('content-length', 0))
# 創(chuàng)建進(jìn)度條
progress_bar = tqdm(
desc=filename,
total=total_size,
unit='iB',
unit_scale=True,
unit_divisor=1024,
)
# 寫入文件
with open(filename, 'wb') as f:
for chunk in response.iter_content(chunk_size=chunk_size):
f.write(chunk)
progress_bar.update(len(chunk))
progress_bar.close()
print(f"\n文件已保存到: {os.path.abspath(filename)}")
return filename
except requests.exceptions.RequestException as e:
print(f"下載失敗: {e}")
return None
# 使用示例
download_file("https://example.com/sample.pdf", "my_document.pdf")
總結(jié)
Python提供了多種下載文件的方法,從簡(jiǎn)單的urllib到功能強(qiáng)大的requests庫(kù),再到結(jié)合多線程/異步的優(yōu)化方案。根據(jù)實(shí)際需求選擇合適的方法:
- 簡(jiǎn)單下載:
requests.get()+ 文件寫入 - 大文件下載:流式下載 + 分塊寫入
- 需要進(jìn)度顯示:結(jié)合
tqdm - 高并發(fā)需求:多線程/異步下載
- 特殊需求:代理、斷點(diǎn)續(xù)傳等高級(jí)功能
掌握這些技術(shù)后,你可以輕松應(yīng)對(duì)各種文件下載場(chǎng)景,構(gòu)建更健壯的Python應(yīng)用程序。
到此這篇關(guān)于從基礎(chǔ)到進(jìn)階詳解Python下載文件的方法完整指南的文章就介紹到這了,更多相關(guān)Python下載文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python實(shí)現(xiàn)一鍵下載并整合統(tǒng)計(jì)年鑒Excel文件
- Python文件解析之Excel/Word/PDF的解析、處理、預(yù)覽與下載
- Python+Paramiko編寫簡(jiǎn)單的SFTP文件上傳下載工具類
- 使用Python實(shí)現(xiàn)帶進(jìn)度條的異步多文件下載器
- 使用Python協(xié)程實(shí)現(xiàn)支持?jǐn)帱c(diǎn)續(xù)傳的文件下載器
- Python多線程實(shí)現(xiàn)大文件快速下載的代碼實(shí)現(xiàn)
- Python實(shí)現(xiàn)下載監(jiān)控工具類:自動(dòng)檢測(cè)并移動(dòng)下載文件
- Python實(shí)現(xiàn)批量下載文件的代碼詳解
相關(guān)文章
Python使用pdfplumber庫(kù)高效解析PDF文件
PDF 文件是日常辦公和數(shù)據(jù)處理中常見(jiàn)的文件格式,而 pdfplumber 是一個(gè)專為 PDF 文件解析設(shè)計(jì)的 Python 庫(kù),可以輕松提取文本、表格、圖像等內(nèi)容,本文將介紹 pdfplumber 的基本功能、使用方法,以及在實(shí)際場(chǎng)景中的應(yīng)用,需要的朋友可以參考下2024-11-11
python 實(shí)現(xiàn)查找文件并輸出滿足某一條件的數(shù)據(jù)項(xiàng)方法
今天小編就為大家分享一篇python 實(shí)現(xiàn)查找文件并輸出滿足某一條件的數(shù)據(jù)項(xiàng)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06
一文總結(jié)學(xué)習(xí)Python的14張思維導(dǎo)圖
一文總結(jié)學(xué)習(xí)Python的14張思維導(dǎo)圖,本文涵蓋了Python編程的核心知識(shí),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
tensorflow中tf.slice和tf.gather切片函數(shù)的使用
今天小編就為大家分享一篇tensorflow中tf.slice和tf.gather切片函數(shù)的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01
Python3 實(shí)現(xiàn)將bytes圖片轉(zhuǎn)jpg格式
這篇文章主要介紹了Python3 實(shí)現(xiàn)將bytes圖片轉(zhuǎn)jpg格式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03
教你如何在Pycharm中導(dǎo)入requests模塊
這篇文章主要介紹了教你如何在Pycharm中導(dǎo)入requests模塊,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
python 數(shù)據(jù)提取及拆分的實(shí)現(xiàn)代碼
這篇文章主要介紹了python 數(shù)據(jù)提取及拆分的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
python分析inkscape路徑數(shù)據(jù)方案簡(jiǎn)單介紹
這篇文章主要介紹了python分析inkscape路徑數(shù)據(jù)方案簡(jiǎn)單介紹,文章通過(guò)圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-09-09
python 爬取古詩(shī)文存入mysql數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了python 爬取古詩(shī)文存入mysql數(shù)據(jù)庫(kù)的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
Python實(shí)現(xiàn)檢測(cè)文件是否存在的方法完整指南
Python作為一門強(qiáng)大的編程語(yǔ)言,提供了多種方法來(lái)檢測(cè)文件存在性,本文將深入探討Python中文件存在性檢測(cè)的各種方法,大家可以根據(jù)需要進(jìn)行選擇2025-09-09

