
本文介绍在批量下载大量 zip/rar/7z 档案后,如何通过 python 程序化、鲁棒地验证其完整性,涵盖魔数校验、库级测试方法、异常捕获策略及实际工程优化建议。
本文介绍在批量下载大量 zip/rar/7z 档案后,如何通过 python 程序化、鲁棒地验证其完整性,涵盖魔数校验、库级测试方法、异常捕获策略及实际工程优化建议。
在跨网络环境(如受 GFW 干扰)、低速限流(NexusMods 非会员 1 MiB/s)且高并发下载的场景下,归档文件极易因传输中断、连接重置或字节截断而损坏。仅靠文件大小或魔数(magic bytes)校验远远不够——例如 .zip 文件即使魔数 b'PK\x03\x04' 正确、长度未变,仍可能因 LZ77 距离编码错误导致解压失败(报错 invalid distance too far back)。因此,真正的完整性验证必须深入归档结构与压缩数据层。
推荐采用三层次验证策略:
-
基础魔数预筛(快速排除明显非法文件)
MAGIC_MAP = { b'PK\x03\x04': ('.zip', '.dazip'), b'Rar!\x1a\x07': '.rar', b'7z\xbc\xaf\'\x1c': '.7z', }读取文件头 8 字节,匹配对应格式。注意:.dazip 是 NexusMods 常见的重命名 ZIP,需一并纳入。
-
库原生测试方法(核心验证)
各主流库均提供轻量级完整性检查接口,不提取文件,仅校验元数据与压缩流:- zipfile.ZipFile.testzip():返回首个损坏文件名(None 表示正常),但可能抛出 OSError、BadZipFile 或底层 zlib/LZMA 异常。
- rarfile.RarFile.testrar():返回 None 或损坏文件名;异常包括 rarfile.BadRarFile(含 read failed / Corrupt file 等子消息)。
- py7zr.SevenZipFile.test() + testzip():test() 快速校验头部,testzip() 深度校验每个条目;异常以 py7zr.Bad7zFile 和 lzma.LZMAError 为主。
-
统一异常兜底处理(工程关键)
实践表明,损坏类型与异常种类高度耦合,但无需穷举所有异常。应捕获与归档解析强相关的明确异常类,并记录原始错误信息用于诊断:from zipfile import BadZipFile from rarfile import BadRarFile from py7zr import Bad7zFile import lzma, zlib CORRUPTION_EXCEPTIONS = ( BadZipFile, OSError, zlib.error, BadRarFile, Bad7zFile, lzma.LZMAError ) try: result = verifier(path) if result is not None: # test* 方法返回损坏文件名 raise ValueError(f"Corrupted entry found: {result}") except CORRUPTION_EXCEPTIONS as e: print(f"[CORRUPT] {path} → {type(e).__name__}: {e}") BAD_FILES.add(path)
⚠️ 注意事项:
- 避免裸 except::会吞掉 KeyboardInterrupt、MemoryError 等系统级异常,改用显式异常元组。
- 分卷归档需特殊处理:如 hdr.2.rar 等分卷文件,rarfile 会报 Need to start from first volume,需提前识别 *.part*.rar 或按命名规则聚合分卷再验证。
- 性能权衡:ThreadPoolExecutor(而非 asyncio 包裹同步库)是正确选择——zipfile/rarfile/py7zr 均为 CPU/IO 密集型操作,异步无法加速,反而增加调度开销;线程数建议设为 min(8, os.cpu_count() * 2)。
- 内存安全:大文件(如 >500MB)验证时,py7zr 可能触发高内存占用,可配合 SevenZipFile(file, password=None, filters=None) 显式禁用不必要的解密/过滤逻辑。
最终,一个健壮的批量验证流程应输出明确的损坏文件列表,并支持后续自动重试下载或人工干预。你已验证的 6 个损坏文件(含 4 个分卷)正是该策略有效性的直接证明——它不止发现静默损坏,更将“分卷缺失”这一业务语义错误也纳入了质量门禁。

















