Python websocket-client连接wss端点报Handshake status 400 Bad Request如何解决?
错误产生原因
你遇到的400错误和鉴权无关,是请求本身不符合服务端规范导致的,具体原因如下:
- 你访问的是Socket.IO协议封装的WebSocket服务,不是原生裸WebSocket,你直接用原生websocket库连接,没有遵循Socket.IO的握手、报文、会话管理规则。你硬编码在URL里的
sid是Socket.IO的临时会话ID,每次新连接都会重新生成,使用过期/无效的sid会直接被服务端返回400。 - 你给
create_connection传入的headers是json.dumps序列化后的字符串,而该接口要求传入dict类型的请求头,服务端无法解析格式错误的请求头,直接返回400。 - 你定义headers的代码里
Cookie行末尾缺少逗号,本身就存在Python语法错误。 - 你写的
json.dumps(42["s_m","DOGETRY"])属于完全错误的语法:42是整数类型,不能用[]进行索引操作,就算握手成功,运行到这行也会直接抛出异常。Socket.IO的42是报文类型前缀,不需要也不能放到JSON序列化内容里。 - 你没有完成Socket.IO的标准握手流程:你提到的
2probe是客户端发的握手探针,3是服务端返回的探针响应,未完成这一步就直接发业务消息,也会被服务端拒绝。
修复方案
不要手动处理Socket.IO的底层逻辑,直接用官方封装的客户端库即可,具体操作如下:
- 安装依赖库
pip install python-socketio python-engineio websocket-client
- 替换原有代码,使用socket.io客户端完成连接和订阅
import socketio # 开启自动重连 sio = socketio.Client(reconnection=True, ssl_verify=True) @sio.event def connect(): print("连接建立成功,开始订阅DOGETRY行情") # 直接调用emit发业务事件,库会自动处理成符合规范的报文格式 sio.emit("s_m", "DOGETRY") # 监听所有返回事件 @sio.on("*") def handle_message(event, data): print(f"事件:{event},数据:{data}") @sio.event def disconnect(): print("连接已断开") # 连接时仅填Socket.IO服务根路径,EIO、transport、sid等参数会自动生成补全 sio.connect( url="https://www.bitexen.com/v2/socket.io/", transports=["websocket"], headers={ 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7', 'Origin': 'https://www.bitexen.com', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', 'Cookie': '从浏览器开发者工具中复制的有效Cookie内容' } ) # 保持连接监听消息 sio.wait()
- 补充注意事项
- 从浏览器获取的Cookie存在有效期,过期后需要重新复制替换,否则会触发鉴权失败。
- 如果需要模拟浏览器的完整行为,可以配合无头浏览器工具获取Cookie,避免手动复制的问题。
内容的提问来源于stack exchange,提问作者Mustafa Güngör
相关产品推荐
相关产品推荐

