批量提取URL区间zip包内tif文件报BadZipFile错误解决方法
问题根因
抛出BadZipFile: File is not a zip file的核心原因如下:
- URL拼接规则错误:目标数据集的压缩包命名要求k后的编号为两位补零格式(比如1号包对应
k01.zip而非k1.zip),1-9号包的URL实际返回404错误页,不是zip二进制内容 - 存在冗余请求:每个资源地址重复发送2次GET请求,第一次请求结果完全未使用,额外浪费带宽
- 无合法性校验:拿到响应内容后没有校验请求状态、文件格式,直接把非zip的错误响应内容传给ZipFile解析,直接触发报错
- 变量名冲突:先后用
filename存储压缩包名、压缩包内部文件名,存在变量覆盖风险
修复后可运行代码
import requests from zipfile import ZipFile, BadZipFile from io import BytesIO print('Downloading started') save_path = '/content/gdrive/My Drive' # 遍历1-42号包 for number in range(1, 43): # 编号补两位零,匹配官方资源命名规则 url = f'https://downloadagiv.blob.core.windows.net/dhm-vlaanderen-ii-dsm-raster-1m/DHMVIIDSMRAS1m_k{number:02d}.zip' print(f'Processing {url}') try: req = requests.get(url, timeout=30) # 校验请求状态 if req.status_code != 200: print(f'Download failed for {url}, status code: {req.status_code}, skip') continue # 校验是否为zip格式(zip文件头固定为PK开头) if not req.content.startswith(b'PK'): print(f'Response is not a valid zip file for {url}, skip') continue zip_file = ZipFile(BytesIO(req.content)) # 遍历压缩包内文件提取tif for inner_file in zip_file.namelist(): if inner_file.endswith('.tif'): zip_file.extract(inner_file, save_path) print(f'Process completed for k{number:02d}.zip') except BadZipFile: print(f'Corrupted zip file for k{number:02d}.zip, skip') except Exception as e: print(f'Error processing k{number:02d}.zip: {str(e)}, skip') print('All tasks finished')
关键优化说明
- 修正URL编号格式,用
{number:02d}实现两位自动补零,匹配资源实际命名规则,解决1-9号包404的核心问题 - 删除重复的无效GET请求,新增超时设置避免请求长时间卡死
- 增加多层校验逻辑:先判断HTTP请求是否成功,再判断返回内容是否符合zip文件头特征,从源头避免把错误内容传给ZipFile
- 新增异常捕获逻辑,单个文件下载失败、损坏时不会中断整个批量处理流程
- 修复变量名冲突问题,明确区分压缩包文件名和压缩包内部存储的文件名
- 增加处理进度打印,方便快速定位异常文件
内容的提问来源于stack exchange,提问作者Yuri HF
相关产品推荐
相关产品推荐

