使用PHP脚本批量下载20万+图片的性能优化及权限问题咨询
批量图片下载问题优化方案
现有代码核心问题
你当前的串行下载逻辑+无超时设置是慢的核心原因:
file_get_contents默认没有超时限制,碰到403权限拒绝、网络卡顿的资源会长时间挂起等待,拖慢整体进度- 所有请求串行执行,上一个请求结束才会发起下一个,20万级的请求量串行跑耗时必然超长
- 没有提前校验响应状态,权限错误的请求也要等完整响应返回才会结束,浪费大量时间
具体优化方案
1. 替换网络请求方式,跳过权限异常资源
弃用file_get_contents,改用CURL实现请求,自定义超时时间,遇到401/403权限类状态码直接终止请求跳过,示例单请求逻辑:
function downloadImage(string $imageUrl, string $savePath): bool { $ch = curl_init($imageUrl); // 设置5秒连接超时,10秒总超时,可根据自身网络调整 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 不输出响应头,只拿body curl_setopt($ch, CURLOPT_HEADER, 0); // 要求跟随重定向 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 先拿到响应状态码再判断是否要下载内容 curl_setopt($ch, CURLOPT_NOBODY, 1); curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 权限类错误直接跳过 if (in_array($httpCode, [401, 403, 404])) { curl_close($ch); return false; } // 状态码正常再开启body下载 curl_setopt($ch, CURLOPT_NOBODY, 0); $fp = fopen($savePath, 'w'); curl_setopt($ch, CURLOPT_FILE, $fp); $result = curl_exec($ch); curl_close($ch); fclose($fp); return $result !== false; }
2. 开启并发下载大幅提效
用CURL的curl_multi系列函数实现并发请求,同时跑1050个下载任务(可根据自身带宽调整并发数),速度比串行提升1040倍,适配20万级的下载量完全没问题。
3. 提前批量过滤无效URL
如果需要更极致的效率,可以先遍历所有CSV里的URL,批量发HEAD请求提前筛掉所有非200状态的异常URL,后续下载阶段只处理有效URL,避免下载阶段浪费资源。
PHP和Python下载速度对比
两者没有本质差距。图片下载属于IO密集型任务,速度瓶颈在网络带宽、并发数配置,和编程语言本身关系很小。如果会用Python的aiohttp+asyncio写异步并发逻辑,写法会比PHP的curl_multi更简洁,但如果还是写串行逻辑,速度和你现在的PHP代码一样慢,没必要硬换编程语言,优化现有PHP逻辑就足够满足需求。
内容的提问来源于stack exchange,提问作者nazmul mondal
相关产品推荐
相关产品推荐

