如何利用Binance API高效批量获取BTC、ETH相关订单簿?
高效获取币安BTC/ETH相关交易对订单簿的优化方案
这个问题我之前也遇到过,同步循环调用REST接口确实效率极低,而且很容易触碰到币安的API限流机制,这里给你几个高效的优化方案,既能大幅提升速度,又能降低被封禁的风险:
1. 使用WebSocket实时订阅(最推荐)
币安提供了WebSocket深度数据推送服务,相比REST请求,它能实时推送增量/全量订单簿数据,一次连接就能订阅多个交易对,完全避免了频繁发起HTTP请求的问题,效率提升非常明显。
实现思路:
- 先通过币安API获取所有以BTC/ETH为计价货币的交易对
- 使用币安的合并流(multi-stream)WebSocket接口,一次性订阅所有目标交易对的深度频道
- 接收并处理实时推送的深度数据(如果需要完整订单簿,可先调用一次REST接口获取全量,再用WebSocket增量更新)
示例代码:
import websockets import asyncio import json from binance.client import Client async def handle_depth_updates(): # 第一步:获取所有BTC/ETH相关的交易对 client = Client() exchange_info = client.get_exchange_info() target_symbols = [ s['symbol'] for s in exchange_info['symbols'] if s['quoteAsset'] in ['BTC', 'ETH'] ] # 构建WebSocket合并流地址 streams = [f"{symbol.lower()}@depth" for symbol in target_symbols] stream_url = f"wss://stream.binance.com:9443/stream?streams={'/'.join(streams)}" # 连接WebSocket并接收数据 async with websockets.connect(stream_url) as websocket: print(f"已订阅 {len(target_symbols)} 个交易对的深度数据") while True: response = await websocket.recv() data = json.loads(response) # 解析交易对和深度数据 symbol = data['stream'].split('@')[0].upper() depth_data = data['data'] # 这里可以根据需求处理数据,比如存储到数据库/缓存 print(f"[{symbol}] 买一价: {depth_data['bids'][0][0]}, 卖一价: {depth_data['asks'][0][0]}") if __name__ == "__main__": asyncio.run(handle_depth_updates())
2. 异步HTTP请求(如果偏好REST接口)
如果不需要实时数据,只是一次性批量获取订单簿,用异步HTTP请求替代同步循环,能把请求时间从5分钟压缩到几十秒内,同时通过并发控制避免触发限流。
实现思路:
- 使用
aiohttp库发起异步请求 - 用信号量(Semaphore)限制并发数(比如20-30),确保不超过币安的API权重限制(
get_order_book的权重为1,币安默认每分钟允许1200次权重为1的请求) - 添加简单的重试机制,处理限流情况
示例代码:
import aiohttp import asyncio from binance.client import Client async def fetch_single_depth(session, symbol, semaphore): async with semaphore: url = "https://api.binance.com/api/v3/depth" params = { 'symbol': symbol, 'limit': 100 # 可选,控制返回的订单档数,默认100,最大1000 } async with session.get(url, params=params) as response: # 处理限流(429状态码) if response.status == 429: retry_after = int(response.headers.get('Retry-After', 10)) await asyncio.sleep(retry_after) return await fetch_single_depth(session, symbol, semaphore) return await response.json() async def batch_fetch_depths(): # 获取目标交易对 client = Client() exchange_info = client.get_exchange_info() target_symbols = [ s['symbol'] for s in exchange_info['symbols'] if s['quoteAsset'] in ['BTC', 'ETH'] ] # 限制并发数,避免触发限流 semaphore = asyncio.Semaphore(20) async with aiohttp.ClientSession() as session: # 创建所有请求任务 tasks = [ fetch_single_depth(session, symbol, semaphore) for symbol in target_symbols ] # 批量执行任务 results = await asyncio.gather(*tasks) # 整理成交易对->订单簿的字典 depth_map = {target_symbols[i]: results[i] for i in range(len(target_symbols))} print(f"已完成 {len(depth_map)} 个交易对的订单簿获取") return depth_map if __name__ == "__main__": asyncio.run(batch_fetch_depths())
额外注意事项
- 筛选交易对:不要手动维护交易对列表,通过
get_exchange_info接口动态获取,避免遗漏或错误 - 权重监控:可以通过响应头的
X-MBX-USED-WEIGHT-1M字段查看当前分钟内已使用的权重,避免超过限额 - 数据精简:如果不需要全量订单簿,设置
limit参数减少返回数据量,提升请求速度
内容的提问来源于stack exchange,提问作者user5043848
相关产品推荐
相关产品推荐

