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

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.

相关推荐
热点推荐
新婚15天就爆不伦!日谐星床战照外泄 人妻私讯「穿最色内裤」求欢

新婚15天就爆不伦!日谐星床战照外泄 人妻私讯「穿最色内裤」求欢

ETtoday星光云
2026-05-14 15:58:05
访华途中,特朗普突然发文!一句话引爆中美舆论,拜登被骂惨了

访华途中,特朗普突然发文!一句话引爆中美舆论,拜登被骂惨了

菁菁子衿
2026-05-15 15:40:44
37岁小托马斯回归绿军!获聘担任球探 至今仍未正式宣布退役

37岁小托马斯回归绿军!获聘担任球探 至今仍未正式宣布退役

罗说NBA
2026-05-15 07:16:41
中美是否在农业方面达成协议?外交部:愿同美方不断拉长合作清单

中美是否在农业方面达成协议?外交部:愿同美方不断拉长合作清单

澎湃新闻
2026-05-15 15:30:26
特朗普起飞后,日本传来消息!高市派出女大臣来华,也想破冰了

特朗普起飞后,日本传来消息!高市派出女大臣来华,也想破冰了

至今
2026-05-15 13:36:38
特朗普爱吃的两道中国菜,好多老外都猜不到

特朗普爱吃的两道中国菜,好多老外都猜不到

阿莱美食汇
2026-05-15 00:03:02
白左圣母被驱赶出家:还会说有一天我们也是难民吗

白左圣母被驱赶出家:还会说有一天我们也是难民吗

侠客栈
2026-05-14 12:43:23
情怀难抵现实!即使骑士能挺进东决,41岁詹姆斯依然回归无望!

情怀难抵现实!即使骑士能挺进东决,41岁詹姆斯依然回归无望!

田先生篮球
2026-05-14 13:43:57
正式取消!知名985高校:公众进校不用预约了

正式取消!知名985高校:公众进校不用预约了

南方都市报
2026-05-14 13:02:01
特朗普突然透露:北京明确表态,不会向伊朗提供军援

特朗普突然透露:北京明确表态,不会向伊朗提供军援

桂系007
2026-05-14 23:59:15
故宫建造时使用的木材,来自哪里?为何这些木材至今没有腐烂

故宫建造时使用的木材,来自哪里?为何这些木材至今没有腐烂

云霄纪史观
2026-05-15 01:49:45
1-2!0-3!国足U17倒下,亚洲杯接近出局,创22年耻辱纪录

1-2!0-3!国足U17倒下,亚洲杯接近出局,创22年耻辱纪录

阿晞体育
2026-05-15 14:35:09
张柏芝为19岁儿子选国产新车,母爱选择显心意

张柏芝为19岁儿子选国产新车,母爱选择显心意

街上的行人很刺眼
2026-05-15 02:59:23
一个人最大的本事,就是解决问题的能力!(深度好文)

一个人最大的本事,就是解决问题的能力!(深度好文)

辛东方
2026-02-12 08:00:03
第一次和男友同居:我直接惊呆了,原来男女私下可爱到犯规

第一次和男友同居:我直接惊呆了,原来男女私下可爱到犯规

那年秋天
2026-05-15 09:00:11
基本盘被指用来嘲讽有爱国情怀的人

基本盘被指用来嘲讽有爱国情怀的人

映射生活的身影
2026-05-13 21:13:11
一座天坛,横跨51年:美国总统再次踏上中美交往的历史现场

一座天坛,横跨51年:美国总统再次踏上中美交往的历史现场

澎湃新闻
2026-05-14 13:34:30
张本美和真敢说!发布会直言:王曼昱赛场胆怯,出手不果断太犹豫

张本美和真敢说!发布会直言:王曼昱赛场胆怯,出手不果断太犹豫

观鱼听雨
2026-05-14 22:25:52
水汽堪比盛夏,超长降雨带跨越千里,局地可能大暴雨!北京傍晚有雨,未来三天持续阴雨

水汽堪比盛夏,超长降雨带跨越千里,局地可能大暴雨!北京傍晚有雨,未来三天持续阴雨

鲁中晨报
2026-05-15 13:34:35
最美女星坏事干尽:三次入狱、鼓励丈夫肉体出轨、被摘5个器官

最美女星坏事干尽:三次入狱、鼓励丈夫肉体出轨、被摘5个器官

临云史策
2026-05-15 13:49:40
2026-05-15 16:19:00
小蜗牛IT
小蜗牛IT
分享程序员日常和知识点
261文章数 83关注度
往期回顾 全部

科技要闻

两年联姻一地鸡毛,传苹果OpenAI濒临决裂

头条要闻

女游客以1分钱拍下标价1980元的三亚海景房 酒店回应

头条要闻

女游客以1分钱拍下标价1980元的三亚海景房 酒店回应

体育要闻

德约科维奇买的球队,从第6级联赛升入法甲

娱乐要闻

方媛为何要来《桃花坞6》没苦硬吃?

财经要闻

特朗普的北京时刻

汽车要闻

双零重力座椅/AI智能体/调光天幕 启境GT7内饰发布

态度原创

本地
健康
旅游
艺术
公开课

本地新闻

用苏绣的方式,打开江西婺源

专家揭秘干细胞回输的安全风险

旅游要闻

天坛最佳拍照机位火了!本台记者率先发现→

艺术要闻

一个北大 “反卷教授” 的意外走红

公开课

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

无障碍浏览 进入关怀版