爬取websockets实时数据

爬取websockets实时数据

web前后端传输场景有一种不是 http/https协议的请求方式,而是通过websockets来进行服务端对客户端主动发起数据推送,常见的比如弹幕,直播,股票等数据,对于实时性更新比较强,所以需要更加频繁的数据交互,而爬取webscoket数据的方式也是类同的。这里介绍2个异步爬取websocket的库,首先是websockets

import asyncio
import websockets
from datetime import datetime
async def hello(uri):
    async with websockets.connect(uri) as websocket:
        while True: 
        	await websocket.send(b'AioWebSocket - Async WebSocket Client')
        	mes = await websocket.recv()
        	print('{time}-Client receive: {rec}'
        	      .format(time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), rec=mes))
asyncio.get_event_loop().run_until_complete(
    hello('ws://echo.websocket.org'))

socket一般是跟asyncio异步进行配合使用,把目标ws或者wss地址丢进事件循环,ws跟wss的关系跟http与https的关系差不多,怎么查看呢,比如

打开这个网站以后在控制台里选择ws,

可以看到wss请求就是socket的地址,一般来说,101就是请求成功了,打开Frames可以观察到客户端跟服务器的一个交互情况,箭头朝上是客户端发送给服务器的参数,朝下就是服务器返回的数据,init操作一般客户端会帮我们完成,我们只要把要抓取的目标数据发送出去就好

除了上面的websockets外,还可以使用aiowebsocket,基本用法如下

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
        message = b'AioWebSocket - Async WebSocket Client'
        while True:
            await converse.send(message)
            print('{time}-Client send: {message}'
                  .format(time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), message=message))
            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 = 'ws://echo.websocket.org'
        asyncio.get_event_loop().run_until_complete(startup(remote))
    except KeyboardInterrupt as exc:
        logging.info('Quit.')

依然是把异步代码放到asyncio的事件循环里面执行,上面的代码只是拿取,并没有演示向服务器提交数据,下面模仿浏览器的请求

import asyncio
import logging
from datetime import datetime
from aiowebsocket.converses import AioWebSocket
import json
async def startup(uri):
    async with AioWebSocket(uri) as aws:
        converse = aws.manipulator
        # 客户端给服务端发送消息
        await converse.send('{"type":"GQL_START","id":"2","query":{"id":"14","variables":{}},"span":{}}')
        while True:
            mes = await converse.receive()
            dict_ = json.loads(mes)
            print(dict_)
if __name__ == '__main__':
    remote = 'wss://neotracker.io/graphql'
        asyncio.get_event_loop().run_until_complete(startup(remote))
    except KeyboardInterrupt as exc:
        logging.info('Quit.')

运行以后就会不断返回数据到客户端,由于返回的数据是一个字符串包着的字典,json.loads转换一下就好了

然后如果你使用mac运行的时候,发现报错如下

SSL handshake failed on verifying the certificate
protocol: <asyncio.sslproto.SSLProtocol object at 0x1071ec7b8>