Python中如何使用requests库编写下载脚本?

代码如下

r = requests.get(url,  stream = True,timeout = 10)
stream_size = r.headers['Content-Length'] #获取下载文件大小
with open(name + '.mp4', 'wb') as f:
    for chunk in r.iter_content(chunk_size = 1024):
    f.write(chunk) #有时候会卡在这里,即一直在等待下一个 chunk。

有时候下载视频,服务器不会返拒绝超时之类的错误(能返回错误倒是好解决),但就是不返回下个 chunk 数据,一直等啊等 所以脚本有时候就卡在那不动了,有办法避免这种情况吗? 获取下个 chunk 值这一段可以加上 timeout 的阈值吗?


Python中如何使用requests库编写下载脚本?

1 回复

import requests
import os
from tqdm import tqdm  # 进度条库,可选

def download_file(url, save_path=None, chunk_size=8192):
    """
    下载文件到本地
    
    Args:
        url: 文件下载链接
        save_path: 保存路径(包含文件名),默认为url中的文件名
        chunk_size: 分块大小,默认8KB
    """
    try:
        # 发送HEAD请求获取文件信息
        head_resp = requests.head(url, allow_redirects=True)
        head_resp.raise_for_status()
        
        # 获取文件名(优先使用Content-Disposition,否则从URL提取)
        if 'content-disposition' in head_resp.headers:
            filename = head_resp.headers['content-disposition'].split('filename=')[-1].strip('"\'')
        else:
            filename = url.split('/')[-1] or 'downloaded_file'
        
        # 确定保存路径
        if save_path is None:
            save_path = filename
        elif os.path.isdir(save_path):
            save_path = os.path.join(save_path, filename)
        
        # 获取文件大小(用于进度条)
        file_size = int(head_resp.headers.get('content-length', 0))
        
        # 发送GET请求下载文件
        print(f"开始下载: {filename}")
        resp = requests.get(url, stream=True)
        resp.raise_for_status()
        
        # 下载并保存文件
        with open(save_path, 'wb') as f, tqdm(
            desc=filename,
            total=file_size,
            unit='B',
            unit_scale=True,
            unit_divisor=1024,
        ) as bar:
            for chunk in resp.iter_content(chunk_size=chunk_size):
                if chunk:
                    f.write(chunk)
                    bar.update(len(chunk))
        
        print(f"下载完成: {save_path}")
        return save_path
        
    except requests.exceptions.RequestException as e:
        print(f"下载失败: {e}")
        return None

# 使用示例
if __name__ == "__main__":
    # 示例1:基本下载
    download_file("https://example.com/file.zip")
    
    # 示例2:指定保存路径
    download_file("https://example.com/image.jpg", "my_image.jpg")
    
    # 示例3:保存到目录
    download_file("https://example.com/document.pdf", "./downloads/")

核心要点:

  1. 使用stream=True分块下载大文件,避免内存溢出
  2. 通过HEAD请求先获取文件信息(大小、文件名)
  3. iter_content()逐块写入文件
  4. 添加进度条提升用户体验(tqdm可选)
  5. 完善的异常处理

一句话建议:记得加异常处理和进度显示。

回到顶部