如何保存WebSocket接收的数据?订阅成功但代码返回空列表与DataFrame
解决GDAX WebSocket数据无法存入列表/DataFrame的问题
嘿,我看你在尝试用GDAX的WebSocket客户端收集数据,结果却得到了空列表和空DataFrame——这个问题我之前也碰到过,主要是没搞懂WebSocket客户端的异步运行逻辑,还有列表操作的小坑。
先给你拆解下原代码的几个问题:
wsClient.start()是用来异步启动WebSocket客户端的方法,它不会返回可迭代的数据,所以你写的for i in wsClient.start()根本遍历不到任何内容。- 列表的
append()方法是原地修改列表,但它返回的是None,所以df1 = df1.append(...)会直接把df1变成None,这也是导致空列表的关键原因之一。 - 重复调用
wsClient.start()完全没必要,启动一次就够了,多次调用只会造成混乱。
接下来给你一个能正常工作的方案,核心思路是继承官方的WebsocketClient类,重写消息处理方法来收集数据,同时用线程锁保证多线程环境下的数据安全(因为WebSocket客户端是在后台线程运行的):
首先导入需要的依赖:
import pandas as pd from gdax import WebsocketClient # 如果这个库装不了,试试用cbpro:from cbpro import WebsocketClient from threading import Lock import time
然后自定义一个用来收集数据的客户端类:
class DataCollector(WebsocketClient): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.data_list = [] self.lock = Lock() # 线程安全锁,防止多线程写入时的数据冲突 def on_message(self, message): # 这里可以根据需求过滤消息类型,比如只保留ticker数据 if message.get('type') == 'ticker': with self.lock: self.data_list.append(message) def on_close(self): print("WebSocket连接已关闭")
然后就可以用这个类来收集数据并转成DataFrame了:
# 初始化客户端,订阅LTC-USD的数据流 collector = DataCollector(url="wss://ws-feed.gdax.com", products=["LTC-USD"]) # 启动客户端(后台线程运行,不会阻塞主线程) collector.start() # 让客户端收集10秒的数据,你可以根据需求调整这个时间,或者用其他方式控制停止时机 time.sleep(10) # 停止客户端连接 collector.close() # 把收集到的数据转成DataFrame df = pd.DataFrame(collector.data_list) print(df.head())
几个关键点说明:
- 重写
on_message方法:每次WebSocket收到消息时,这个方法会被自动调用,我们在这里把符合条件的数据存入列表。 - 线程锁的作用:因为WebSocket客户端在后台线程运行,主线程和后台线程同时操作列表可能会出问题,用
Lock可以保证数据写入的安全性。 - 控制收集时长:用
time.sleep()是最简单的测试方式,如果需要持续收集,可以监听信号(比如Ctrl+C)来触发停止逻辑。
另外提个小提醒:现在GDAX已经改名为Coinbase Pro了,官方推荐用cbpro库代替原来的gdax,如果pip install gdax失败,试试pip install cbpro,导入的时候换成from cbpro import WebsocketClient就行。
内容的提问来源于stack exchange,提问作者RustyShackleford
相关产品推荐
相关产品推荐

