wss协议实际是websocket+SSL,就是在websocket协议上加入SSL层,类似https(http+SSL)。
所以只需要在websocket协议的基础上开启SSL即可支持wss协议。
Web 领域中,用于实现数据'实时'更新的手段有轮询和 WebSocket 这两种。轮询指的是客户端按照一定时间间隔(如 1 秒)访问服务端接口,从而达到 '实时' 的效果,虽然看起来数据像是实时更新的,但实际上它有一定的时间间隔,并不是真正的实时更新。轮询通常采用 拉 模式,由客户端主动从服务端拉取数据。WebSocket 采用的是 推 模式,由服务端主动将数据推送给客户端,这种方式是真正的实时更新。
PHP可以载入WorkerMan搭建WSS服务
WebSocket是一种在单个TCP连接上进行全双工通信的协议。它使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
WebSocket 优点
较少的控制开销:只需要进行一次握手,携带一次请求头信息即可,后续只传输数据即可,相比 HTTP 每次请求都携带请求头,WebSocket 非常省资源。
更强的实时性:由于服务器可以主动推送消息,这使得延迟变得可以忽略不计,相比 HTTP 轮询的时间间隔,WebSocket 可以在相同的时间内进行多次传输。
二进制支持:WebSocket 支持二进制帧,这意味着传输更节省。
……
爬虫面对 HTTP 和 WebSocket
Python 中的网络请求库非常多,Requests 是最常用的请求库之一,它可以模拟发送网络请求。但是这些请求都是基于 HTTP 协议的。在面对 WebSocket 的时候 Requests 就发挥不料作用了,必须使用能够连接 WebSocket 的库。
与 HTTP 请求不同的是,WebSocket 连接地址以 ws 或 wss 开头。连接成功的状态码不是 200,而是 101。
Headers 标签页记录的是 Request 和 Response 信息,而 Frames 标签页中记录的则是双方互传的数据,也是我们需要爬取的数据内容:
从数据顺序中可以看到,客户端先发送:
然后服务端才会推送信息(一直推送):
{"group":"QuoteBin5m:14
在JS中,websocket 的 new WebSocket() 是固定的语法,可以用做我们定位的关键词。
webSocket.send 用于向服务器发送数据
webSocket.onopen 用于指定连接成功后的回调函数
webSocket.onmessage 用于指定收到服务器数据后的回调函数
webSocket.onclose 用于指定连接关闭后的回调函数
websocket.binaryType = ‘arraybuffer’; 用来表示通用的、固定长度的原始二进制数据缓冲区
RPC最重要的是找到入口点。一般消息处理函数为onmessage 或者 addEventListener(“message”)
ws.onmessage = function(event) {
爬虫抓包后需要对二进制数据进行分析解析,获取有价值数据
案例:通过wss抓取BiKi网站上面的虚拟币实时交易数据
发现中间有echart画的图,左边是币种的选择,右边是实时交易买入卖出的内容,也就是我们要抓取的内容。
这些红框画出来的数据,就是我们的目标。
我们先要观察它的特性。
1.动态数据
2.F12进去发现页面上没有数据
用F12进去之后发现这个数据是动态生成的。而且界面上的数据也是参考这个数据。所以得出结论 这个就是我们要寻找的元数据的地方。
Elements看完了,没什么收获,接下来找到network。看有没有什么js文件或者数据是一直在请求的。
我们发现了里面有个叫ws的请求。感觉到这个可能用的是用websocket和服务端 建立的长连接,一直推数据过来。
而且里的request url 是wss ,表明是通过ssl加密的。
然后我们点开message 发现里面会一直收到二进制文件。大多都在200b左右,持续刷新,这个就是我们要的数据。
此时,刷新一下界面。发现有很多绿色的json数据。这个就是网页向服务端请求的数据。请求了之后,服务端才会向你发送想要的数据。
ok 。以上就是怎么寻找我们要的实时交易数据。
那么接下来就是怎么抓取数据
打开vscode ,新建一个 python文件。
安装websocket-client 包:sudo pip3 install websocket-client 或者自己去pip官网下载。
然后看websocket-client包怎么用。
以下 是代码
##13482198105@163.com
import websocket
import ssl
import gzip
import time
import datetime
import json
import demjson
def on_message(ws, message): # 服务器有数据更新时,主动推送过来的数据
# print(message)
ret = gzip.decompress(message).decode("utf-8")
if ('ping' in ret):
return
text = demjson.decode(ret)
print(text)
for index in range(len(text['tick']['data'])):
print('ds='+str(text['tick']['data'][index]['ds']))
print('price='+str(text['tick']['data'][index]['price']))
print('side='+str(text['tick']['data'][index]['side']))
print('vol='+str(text['tick']['data'][index]['vol']))
print('###################分割线#############################')
# print(text.keys())
# print('amount='+str(text['tick']['data'][0]['amount']) )
# print('ds='+str(text['tick']['data'][0]['ds']))
# print('id='+str(text['tick']['data'][0]['id']))
# print('price='+str(text['tick']['data'][0]['price']))
# print('side='+str(text['tick']['data'][0]['side']))
# print('ts='+str(text['tick']['data'][0]['ts']))
# print('vol='+str(text['tick']['data'][0]['vol']))
# 程序报错时,就会触发on_error事件
def on_error(ws, error):
print(error)
# 程序关闭后触发close时间
def on_close(ws):
print("Connection closed ……")
# 连接到服务器之后就会触发on_open事件
def on_open(ws):
# ws.send('{"event":"req","params":{"channel":"review"}}') #获取review数据
# 获取btcusdt
ws.send('{"event": "sub", "params": {"channel": "market_btcusdt_trade_ticker", "cb_id": "btcusdt", "top": 100}}')
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("wss://wspool.mpuuss.top/kline-api/ws",
on_message=on_message,
on_error=on_error,
on_close=on_close)
ws.on_open = on_open
ws.run_forever()
以下是结果数据