如何优化13000条URL校验及图片下载的requests请求?
Python异步批量下载图片优化方案
你当前的同步请求逻辑每个请求都要等待前一个返回才能继续,13000个URL自然耗时极长,改用异步IO可以同时发起多个请求,能把耗时压缩到十几分钟甚至几分钟级别。
前置准备
- 安装所需依赖:
pip install aiohttp aiofiles tqdm - 你之前写的
get_name_path、check_dupe、create_dir、generate_links这些函数可以直接复用,只需要修改下载和请求逻辑即可。
完整可运行代码
import asyncio import aiohttp import aiofiles from tqdm.asyncio import tqdm_asyncio # 你原来的全局变量、自定义函数直接保留在这里即可 # headers = {xxx} # def get_name_path(url): xxx # def check_dupe(name): xxx # def create_dir(): xxx # def generate_links(): xxx # 异步单文件下载逻辑 async def download_single(session, url, semaphore): # 用信号量控制并发数,避免请求过于密集被封IP async with semaphore: try: async with session.get(url, headers=headers) as resp: if resp.status != 200: return name, path = get_name_path(url) if check_dupe(name): return # 异步写入文件 async with aiofiles.open(path, 'wb') as f: await f.write(await resp.read()) except Exception as e: # 异常捕获避免单个请求失败导致整个任务崩溃,可按需添加日志 pass async def main(): folder_path = create_dir() urls = generate_links() # 并发数设置,建议20~50之间,根据目标服务器承受能力调整 semaphore = asyncio.Semaphore(30) async with aiohttp.ClientSession() as session: tasks = [download_single(session, url, semaphore) for url in urls] # 带进度条执行所有任务 await tqdm_asyncio.gather(*tasks, desc="下载进度") if __name__ == "__main__": asyncio.run(main())
注意事项
- 并发数不要设置太高,超过目标服务器的承载阈值会触发限流甚至封IP,测试阶段可以先取100个URL试跑,调整到合适的并发值再全量执行
- 如果遇到SSL证书相关报错,可以在
session.get参数中加ssl=False解决 - 你原来的
save_file函数如果有特殊写入逻辑,只需要把对应同步读写代码替换成aiofiles的异步写法即可,无需修改业务逻辑 - 异常捕获部分可以按需增加失败重试、失败URL记录的逻辑,方便后续补下未成功下载的资源
内容的提问来源于stack exchange,提问作者zezad
相关产品推荐
相关产品推荐

