Python 3.6使用wget.download批量下载文件出现卡滞问题
问题核心成因
- Python第三方
wget包存在天生的网络阻塞缺陷:这个包(并非系统wget命令行工具的封装)内部未对socket读写设置任何超时阈值,所有网络请求默认处于无限等待状态。只要遇到TCP半开连接、服务端丢包、连接被中途掐断但未返回断开信号的情况,程序就会永久卡在数据读取阶段,既不抛出异常也不退出,对应表现就是正在写入的.tmp文件大小固定、完全无进度。 - 叠加目标站点的简单限流机制:你观察到的“累计下载5-10个文件就触发卡滞、重启进程就恢复”的规律,完全匹配站点的基础反爬逻辑——短时间内同一IP无标识连续请求时,站点不会直接返回403错误,而是主动挂起连接、不发送任何响应数据,没有超时机制的程序就会永久停在等待状态。重启进程相当于重新建立了全新的网络会话,绕过了上一次会话累计触发的限流阈值,所以又能正常运行一段时间。
- Python 3.6.9版本的适配缺陷:该版本的全局socket默认超时为永久等待,而对应版本的第三方
wget库没有适配高版本Python的超时控制能力,运行过程中就算系统层检测到连接超时,wget内部的文件读写逻辑也会吞掉超时异常,不会触发重试流程。
落地解决方法
- 强制添加全局socket超时兜底:在程序入口最开头添加全局超时配置,从系统层杜绝永久等待的问题,配置代码:
import socket; socket.setdefaulttimeout(30)
配置后,所有网络请求只要30秒内没有数据传输,就会直接抛出超时异常,不会永久卡在阻塞状态。 - 替换脆弱的第三方
wget.download实现:换用支持超时控制的requests库做流式下载,彻底绕开wget的固有缺陷,参考代码:import requests def download_one_file(url, save_path, timeout=30): # 流式请求避免大文件占用过高内存 resp = requests.get( url, stream=True, timeout=timeout, headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"} ) # 按1MB分块写入文件,避免全程占用过高内存 with open(save_path, 'wb') as f: for chunk in resp.iter_content(chunk_size=1024*1024): if chunk: f.write(chunk) - 增加异常重试逻辑:循环下载时为每个文件的下载流程套一层异常捕获,遇到超时、连接错误时,先删除残留的临时文件,间隔3-5秒自动重试最多3次,不要单次失败就中断整个下载流程。
- 规避站点限流:每下载完成1个文件,主动加1-2秒的随机延时,不要无间隔连续发请求;请求时搭配正常的浏览器标识头,避免被站点识别为爬虫后主动挂起连接。
- 如果不想替换现有wget逻辑,可以增加看门狗机制:单独开一个后台线程,每隔10秒检查当前正在写入的
.tmp文件大小,如果连续30秒文件大小没有变化,就强制中断当前的下载流程,删除残留临时文件后自动重试下一个文件。
内容的提问来源于stack exchange,提问作者KoolGuy90
相关产品推荐
相关产品推荐

