requests库是同步的——发一个请求等它回来再发下一个。当你需要同时发几百个请求,异步方案(aiohttp/httpx)效率是requests的5-10倍。但异步请求的代理配置方式和requests不一样。
为什么异步比同步快那么多
同步请求:发请求→等网络响应(大部分时间在空等)→收到响应→处理→发下一个。异步请求:同时发100个请求→100个请求同时在网络上传输→哪个先回来先处理哪个→不等。代理IP的网络延迟越高,异步的收益越大——因为空等的时间越长。
天行IP静态代理月付6元起(邀请码 blsj),延迟低 的节点配合异步请求效率更高。
aiohttp配代理
import aiohttp
import asyncio
async def fetch(url, proxy):
async with aiohttp.ClientSession() as session:
async with session.get(url, proxy=proxy) as resp:
return await resp.text()
async def main():
proxy = "http://用户名:密码@代理IP:端口"
urls = ["https://目标1", "https://目标2", ...]
tasks = [fetch(url, proxy) for url in urls]
results = await asyncio.gather(*tasks, return_exceptions=True)
return results
asyncio.run(main())注意并发数——asyncio.gather会同时发所有请求,如果urls有1000个就是1000个并发。代理IP的并发上限参考第34篇(ID 13579)。加Semaphore限流:
sem = asyncio.Semaphore(20) # 同时最多20个请求
async def fetch_limited(url, proxy):
async with sem:
# ...httpx配代理——支持异步也支持同步
httpx同时支持同步和异步API,迁移成本比aiohttp低:
import httpx
import asyncio
async def fetch(url, proxy_url):
async with httpx.AsyncClient(proxy=proxy_url) as client:
resp = await client.get(url)
return resp.text
# 同步模式(和requests一样用)
with httpx.Client(proxy="http://代理IP:端口") as client:
resp = client.get(url)代理IP轮换:维护IP池列表,每个请求随机取一个。
import random
proxies = ["http://ip1", "http://ip2", ...]
async def fetch_with_rotate(url):
proxy = random.choice(proxies)
async with httpx.AsyncClient(proxy=proxy, timeout=10) as client:
return await client.get(url)aiohttp vs httpx选择
| 维度 | aiohttp | httpx |
|---|---|---|
| 速度 | 略快(纯异步设计) | 略慢但差距可忽略 |
| API风格 | 独特API | 和requests几乎一样 |
| 代理支持 | proxy参数直接传URL | 和requests用法一致 |
| HTTP/2 | 不支持 | 支持 |
从requests迁移到异步选httpx(API几乎不变),纯新项目追求极致性能选aiohttp。
常见问题
异步请求代理IP被限频怎么办?
加Semaphore控制并发、加asyncio.sleep控制请求间隔、多代理IP分摊、加退避重试。同时100个请求打出去代理服务器可能直接拒绝。
代理认证在httpx里怎么写?
和requests一样:proxy=”http://用户名:密码@IP:端口”。httpx会自动解析认证信息。
异步请求一个失败会不会影响其他的?
return_exceptions=True让异常不中断整个gather。单个请求超时或连接失败不会影响其他请求继续执行。






