爬取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>