基于NATS WebSocket对接Sofascore电竞数据报错及库选型咨询
问题
我要开发WebSocket程序获取Sofascore平台的所有电竞事件数据,分析后需要先发送认证内容再订阅对应赛事。已编写Python代码,但运行时出现认证超时错误,且发现该服务基于NATS网络,找不到支持WebSocket的NATS Python库。
代码实现
import websockets import asyncio from websockets.extensions import permessage_deflate async def esports(): async with websockets.connect('wss://ws.sofascore.com:9222/', compression='deflate') as websocket: msg = await websocket.recv() print(f"From Server: {msg}") t = await websocket.send( 'CONNECT {"no_responders":true,"protocol":1,"verbose":false,"pedantic":false,"user":"none","pass":"none","lang":"nats.ws","version":"1.8.1","headers":true}') await websocket.send("PING") pong = await websocket.recv() print(f"From Server: {pong}") await websocket.send( 'SUB sport.esports 6') while (True): msg = await websocket.recv() print(f"From Server: {msg}") asyncio.get_event_loop().run_until_complete(esports())
错误信息
Traceback (most recent call last): File "C:\Users\Coding\Desktop\websockett.py", line 23, in <module> asyncio.get_event_loop().run_until_complete(esports()) File "C:\Users\Coding\AppData\Local\Programs\Python\Python39-32\lib\asyncio\base_events.py", line 642, in run_until_complete return future.result() File "C:\Users\Coding\Desktop\websockett.py", line 15, in esports await websocket.send( File "C:\Users\Coding\AppData\Roaming\Python\Python39\site-packages\websockets\legacy\protocol.py", line 620, in send await self.ensure_open() File "C:\Users\Coding\AppData\Roaming\Python\Python39\site-packages\websockets\legacy\protocol.py", line 921, in ensure_open raise self.connection_closed_exc() websockets.exceptions.ConnectionClosedError: received 1008 (policy violation) Authentication Timeout; then sent 1008 (policy violation) Authentication Timeout Process finished with exit code 1
解决方案
1. 修复认证超时问题
出现1008认证超时错误,核心原因是NATS over WebSocket协议流程不符合要求,以及消息格式、压缩配置存在问题,调整后的代码如下:
import websockets import asyncio import json from websockets.extensions import permessage_deflate async def esports(): # 精确配置permessage_deflate压缩,匹配服务器要求 extensions = [ permessage_deflate.ClientPerMessageDeflateFactory( server_no_context_takeover=True, client_no_context_takeover=True, ) ] async with websockets.connect( 'wss://ws.sofascore.com:9222/', extensions=extensions, ping_interval=10, # 定期发送PING维持连接 ping_timeout=5 ) as websocket: # 先接收服务器发送的INFO消息(NATS协议第一步) info_msg = await websocket.recv() print(f"服务器INFO: {info_msg}") # 构造符合NATS规范的CONNECT命令,结尾需加CRLF(\r\n) connect_payload = json.dumps({ "no_responders": True, "protocol": 1, "verbose": False, "pedantic": False, "user": "none", "pass": "none", "lang": "nats.ws", "version": "1.8.1", "headers": True }) await websocket.send(f"CONNECT {connect_payload}\r\n") print("已发送CONNECT认证") # 接收服务器的认证响应(OK或ERR) connect_resp = await websocket.recv() print(f"认证响应: {connect_resp}") # 发送PING维持连接,同样需加CRLF await websocket.send("PING\r\n") pong = await websocket.recv() print(f"PONG响应: {pong}") # 订阅电竞主题,SUB命令格式:SUB <主题> <队列组> <会话ID>,队列组为空时保留空格 await websocket.send("SUB sport.esports 6\r\n") print("已订阅sport.esports主题") # 持续接收赛事数据 while True: msg = await websocket.recv() print(f"收到赛事数据: {msg}") asyncio.run(esports())
关键修改点:
- 压缩配置:使用
ClientPerMessageDeflateFactory精确配置permessage_deflate,替代简单的compression='deflate',确保和服务器压缩规则匹配 - 协议流程:严格遵循NATS over WebSocket流程:先接收服务器INFO消息,再发送CONNECT认证,避免超时
- 消息格式:所有NATS命令结尾必须加
\r\n(CRLF),否则服务器无法识别命令 - 连接维持:设置
ping_interval和ping_timeout,定期发送PING包防止连接被服务器断开
2. NATS WebSocket Python库问题
目前官方的nats.py库仅支持TCP连接,没有原生WebSocket支持。你可以基于websockets库自行封装NATS核心命令(CONNECT、PING、SUB、UNSUB等),因为NATS over WebSocket使用文本帧传输,每个命令都是一行带CRLF结尾的字符串,实现成本较低。
内容的提问来源于stack exchange,提问作者CodingLion
相关产品推荐
相关产品推荐

