网易首页 > 网易号 > 正文 申请入驻

Python 如何爬取实时变化的 WebSocket 数据

0
分享至

作为一名爬虫工程师,在工作中常常会遇到爬取实时数据的需求,比如体育赛事实时数据、股市实时数据或币圈实时变化的数据。如下图:

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

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

二、什么是 WebSocket

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

WebSocket 优点

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

爬虫面对 HTTP 和 WebSocket

Python 中的网络请求库非常多,Requests 是最常用的请求库之一,它可以模拟发送网络请求。但是这些请求都是基于 HTTP 协议的。在面对 WebSocket 的时候 Requests 就发挥不料作用了,必须使用能够连接 WebSocket 的库。

三、爬取思路

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

在开发者工具中提供了筛选功能,其中 WS 选项代表只显示 WebSocket 连接的网络请求。

这时候可以看到请求记录列表中有一条名为 realTime 的记录,鼠标左键点击它后,开发者工具会分为左右两栏,右侧列出本条请求记录的详细信息:

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

Headers 标签页记录的是 Request 和 Response 信息,而 Frames 标签页中记录的则是双方互传的数据,也是我们需要爬取的数据内容:

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

从数据顺序中可以看到,客户端先发送:

{"action":"subscribe","args":["QuoteBin5m:14"]}

然后服务端才会推送信息(一直推送):

{"group":"QuoteBin5m:14","data":[{"low":"55.42","high":"55.63","open":"55.42","close":"55.59","last_price":"55.59","avg_price":"55.5111587372932781077","volume":"40078","timestamp":1551941701,"rise_fall_rate":"0.0030674846625766871","rise_fall_value":"0.17","base_coin_volume":"400.78","quote_coin_volume":"22247.7621987324"}]}

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

那么,现在问题来了:

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

四、aiowebsocket

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

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

ReadMe中介绍到:

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

它的安装和其他库一样简单,使用 pip install aiowebsocket 即可。安装好后,我们可以根据 ReadMe 中提供的示例代码来测试:

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' try: asyncio.get_event_loop().run_until_complete(startup(remote)) except KeyboardInterrupt as exc: logging.info('Quit.')

运行后的结果输出为:

2019-03-07 15:43:55-Client send: b'AioWebSocket - Async WebSocket Client' 2019-03-07 15:43:55-Client receive: b'AioWebSocket - Async WebSocket Client' 2019-03-07 15:43:55-Client send: b'AioWebSocket - Async WebSocket Client' 2019-03-07 15:43:56-Client receive: b'AioWebSocket - Async WebSocket Client' 2019-03-07 15:43:56-Client send: b'AioWebSocket - Async WebSocket Client' ……

send 表示客户端向服务端发送的消息

recive 表示服务端向客户端推送的消息

五、编码获取数据

回到这一次的爬取需求,目标网站是莱特币官网:

从刚才的网络请求记录中,我们得知目标网站的 WebSocket 地址为: wss://api.bbxapp.vip/v1/ifcontract/realTime ,从地址中可以看出目标网站使用的是 wss,也就是 ws 的安全版,它们的关系跟 HTTP/HTTPS 一样。aiowebsocket 会自动处理并识别 ssl,所以我们并不需要作额外的操作,只需要将目标地址赋值给连接 uri 即可:

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 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 exc: logging.info('Quit.')

运行代码后观察输出,你会发现什么都没有发生。既没有内容输出,也没有断开连接,程序一直在运行,但是什么都没有:

这是为什么呢?

是对方不接受我方的请求吗?

还是有什么反爬虫限制呢?

实际上,刚才的流程图可以解释这个问题:

整个流程中有一步是需要客户端给服务端发送指定的消息,服务端验证后才会不停推送数据。所以,应该在消息读取前、握手连接后加上消息发送的代码:

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 exc: logging.info('Quit.')

保存后运行,就会看到数据源源不断的推送过来:

到这里,爬虫就能够获取到想要的数据了。

aiowebsocket 做了什么

代码不长,使用的时候只需要将目标网站 WebSocket 地址填入,然后按照流程发送数据即可,那么 aiowebsocket 在这个过程中做了什么呢?

  • 首先,aiowebsocket 根据 WebSocket 地址,向指定的服务端发送握手请求,并校验握手结果。
  • 然后,在确认握手成功后,将数据发送给服务端。
  • 整个过程中为了保持连接不断开,aiowebsocket 会自动与服务端响应 ping pong。
  • 最后,aiowebsocket 读取服务端推送的消息

如果你对Python编程感兴趣,那么记得来小编的Python学习扣群:1017759557,这里有资源共享,技术解答,大家可以在一起交流Python编程经验,还有小编整理的一份Python学习教程,希望能帮助大家更好的学习python。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
刚刚!山东“取消收费”!全体160厘米以下学生终于有“救”了!!(统一身高管理)

刚刚!山东“取消收费”!全体160厘米以下学生终于有“救”了!!(统一身高管理)

山东教育电视台
2026-07-10 07:15:39
秦海璐变卖房产,清空全部资产,凑出近亿身家,绝境兜底救下刘涛

秦海璐变卖房产,清空全部资产,凑出近亿身家,绝境兜底救下刘涛

秋别离
2026-06-13 15:50:00
北约秘书长和日本商议过后,认定中方是乌克兰危机的“推动者”

北约秘书长和日本商议过后,认定中方是乌克兰危机的“推动者”

羽逸地之光
2026-07-09 12:35:47
国家一级女演员陈丽云被逮捕!

国家一级女演员陈丽云被逮捕!

许三岁
2026-03-28 09:24:30
“为哈梅内伊复仇”,伊朗打击美军舰、基地、“爱国者”等!美方:正进行外交努力缓和局势!以色列:做好打伊朗准备,数百架战机随时待命

“为哈梅内伊复仇”,伊朗打击美军舰、基地、“爱国者”等!美方:正进行外交努力缓和局势!以色列:做好打伊朗准备,数百架战机随时待命

每日经济新闻
2026-07-10 10:36:06
沉默45年,中国第二轮"严打"终于来了!目标改变总体战正式打响

沉默45年,中国第二轮"严打"终于来了!目标改变总体战正式打响

职场资深秘书
2026-07-10 17:11:17
快船猛龙交易叫停!需等小卡阴阳合同案出结果 多伦多仍渴望迎回他

快船猛龙交易叫停!需等小卡阴阳合同案出结果 多伦多仍渴望迎回他

罗说NBA
2026-07-10 05:53:30
东软集团被曝下调部分员工公积金缴存比例

东软集团被曝下调部分员工公积金缴存比例

i黑马
2026-07-10 10:04:53
我国34省份性需求报告现实:超30%的男女性欲很强!

我国34省份性需求报告现实:超30%的男女性欲很强!

灯锦年
2026-07-10 12:30:36
广西男篮国手心系家乡,廖三宁十万,庞峥麟一千

广西男篮国手心系家乡,廖三宁十万,庞峥麟一千

林子说事
2026-07-10 16:14:59
四川一男子采菌子疑遭熊袭击死亡,3天后遗体被发现,生前8次拨打家人电话未果

四川一男子采菌子疑遭熊袭击死亡,3天后遗体被发现,生前8次拨打家人电话未果

新京报
2026-07-10 15:47:33
马斯克有句话点醒过我“如果今天我破产了,绝对不会去找工作,而是去做一件能快速产生现金流,并且可以复制放大的事。”

马斯克有句话点醒过我“如果今天我破产了,绝对不会去找工作,而是去做一件能快速产生现金流,并且可以复制放大的事。”

LULU生活家
2026-07-07 20:59:47
离谱!曝一越南男博主宣称广东人其实就是越南人,曾是一个国家

离谱!曝一越南男博主宣称广东人其实就是越南人,曾是一个国家

小徐讲八卦
2026-07-10 16:20:31
洪水漫过蛇场

洪水漫过蛇场

新京报
2026-07-10 11:28:11
从“人傻钱多”到“提桶跑路”,中企这波操作给资源国们上了一课

从“人傻钱多”到“提桶跑路”,中企这波操作给资源国们上了一课

秋狝春苗梦
2026-07-08 17:42:30
台风逼近却晴空万里,很多宁波人蒙了......别被今天的太阳骗了!暴雨大暴雨,个别特大暴雨,马上就要来了

台风逼近却晴空万里,很多宁波人蒙了......别被今天的太阳骗了!暴雨大暴雨,个别特大暴雨,马上就要来了

极目新闻
2026-07-10 14:11:32
埃及各界呼吁抵制梅西!球迷火烧球衣 阿根廷网友向埃及人民道歉

埃及各界呼吁抵制梅西!球迷火烧球衣 阿根廷网友向埃及人民道歉

念洲
2026-07-10 16:11:40
詹姆斯终于想通了!甘愿降薪387万,不考虑以核心身份加盟

詹姆斯终于想通了!甘愿降薪387万,不考虑以核心身份加盟

古事寻踪记
2026-07-10 11:37:02
陈皮搭一物,堪称“祛湿高手”,痰没了湿气散了,清爽轻快!

陈皮搭一物,堪称“祛湿高手”,痰没了湿气散了,清爽轻快!

江江食研社
2026-07-08 15:30:10
小红书700亿的IPO,被一场85万的官司干停了

小红书700亿的IPO,被一场85万的官司干停了

茄小茄说事
2026-07-10 11:41:43
2026-07-10 18:00:50
小蜗牛IT
小蜗牛IT
分享程序员日常和知识点
261文章数 83关注度
往期回顾 全部

科技要闻

中国开启可回收火箭时代

头条要闻

中国商人在泰遭绑架 绑匪:老大要杀人 60万美金能买命

头条要闻

中国商人在泰遭绑架 绑匪:老大要杀人 60万美金能买命

体育要闻

法国VS摩洛哥:谁才是臭外地的?

娱乐要闻

韩国顶流李钟硕与IU官宣分手!

财经要闻

长征十号乙首飞告捷 海上网系回收成功

汽车要闻

长续航智美纯电轿跑 奇瑞风云A9开启预售11.59万起

态度原创

亲子
本地
旅游
房产
公开课

亲子要闻

你考多少分?,笑不活了

本地新闻

重庆人有自己的避暑桃花源 | 夏天就去「酉」风的地方!

旅游要闻

枣庄山亭亮出暑期文旅组合拳 全域活动激活夏日消费活力

房产要闻

海口,终于要发力卖地了!

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版