爬取websocket实时数据

一、什么是websocket

Websocket是一种在单个TCP连接上进行全双工通信的协议。它使得客户端和服务端之间的数据交换变得更加简单,允许服务器主动向客户端推送数据。在Websocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

Websocekt优点:

  • 较少的控制开销:只需要进行一次握手,携带一次请求头信息即可,后续只传输数据即可,相比 HTTP 每次请求都携带请求头,WebSocket 非常省资源。
  • 更强的实时性:由于服务器可以主动推送消息,这使得延迟变得可以忽略不计,相比 HTTP 轮询的时间间隔,WebSocket 可以在相同的时间内进行多次传输。
  • 二进制支持:WebSocket 支持二进制帧,这意味着传输更节省。

二、哪些数据是通过websocket协议传输的

实时数据:比如体育赛事实时数据、股市实时数据或者币圈实时变化的数据。
如下图:

爬取websocket实时数据_第1张图片

Web 领域中,用于实现数据’实时’更新的手段有轮询和 WebSocket 这两种。轮询指的是客户端按照一定时间间隔(如 1 秒)访问服务端接口,从而达到 ‘实时’ 的效果,虽然看起来数据像是实时更新的,但实际上它有一定的时间间隔,并不是真正的实时更新。轮询通常采用 拉 模式,由客户端主动从服务端拉取数据。

WebSocket 采用的是 推 模式,由服务端主动将数据推送给客户端,这种方式是真正的实时更新。

三、爬取思路

这里以莱特币官网 http://www.laiteb.com/ 实时数据为例。WebSocket 的握手只发生一次,所以如果需要通过浏览器开发者工具观察网络请求,则需要在打开页面的情况下,打开浏览器开发者工具,定位到 NewWork 选项卡,并输入或刷新当前页面,才能观察到 WebSocket 的握手请求和数据传输情况。这里以 Chrome 浏览器为例:

2019-08-16 17-07-47屏幕截图爬取websocket实时数据_第2张图片
在开发者个工具提供了筛选功能,其中WS选项代表Websocket连接的网络请求。

与HTTP请求不同的是,Websocket连接地址以ws或wss开头。连接成功的状态码不是200,而是101。

Meessage页面记录双方互传的数据,也是我们需要的数据。

图中绿色箭头向上的数据是客户端发送给服务端的数据,橙色箭头向下的数据是服务端推送给客户端的数据。

从数据顺序可以看到,客户端先发送:
{“action”:“subscribe”,“args”:[“QuoteBin5m:14”]}

然后服务端才一直推送消息

所以整个从发起握手到获得数据的流程为:

爬取websocket实时数据_第3张图片
那么,现在问题来了:

  • 握手怎么弄?
  • 连接保持怎么弄?
  • 消息发送和接收怎么弄?
  • 有什么库可以轻松实现吗?

四、aiowebsocket

Python 库中用于连接 WebSocket 的有很多,但是易用、稳定的有 websocket-client(非异步)、websockets(异步)、aiowebsocket(异步)。

可以根据项目需求选择三者之一,今天介绍的是异步 WebSocket 连接客户端 aiowebsocket。其 Github 地址为: https://github.com/asyncins/aiowebsocket 。

ReadMe中介绍到: AioWebSocket是一个遵循 WebSocket 规范的 异步 WebSocket 客户端,相对于其他库它更轻、更快。

我们得知目标网站的Websocket地址为:wss://api.bbxapp.vip/v1/ifcontract/realTime

代码如下:

import asyncio
import logging
from datetime import datetime
from aiowebsocket.converses import AioWebSocket


async def startup(uri):
    async with AioWebSocket(uri) as aws:
        converse = aws.manipulator
        await converse.send('{"action":"subscribe","args":["QuoteBin5m:14"]}')
        while True:
            mes = await converse.receive()
            print('{time}-Client receive:{rec}'.format(time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), rec=mes))


if __name__ == '__main__':
    remote = 'wss://api.bbxapp.vip/v1/ifcontract/realTime'
    try:
        asyncio.get_event_loop().run_until_complete(startup(remote))
    except KeyboardInterrupt as exec:
        logging.info('Quit.')

运行结果如下:

爬取websocket实时数据_第4张图片

注:本文转载自:https://www.jb51.net/article/157572.htm ,仅供学习使用。

你可能感兴趣的:(python,爬虫)