0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

电子工程师 来源:lp 2019-03-11 09:31 次阅读

一、前言

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

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 中提供的示例代码来测试:

importasyncioimportloggingfromdatetimeimportdatetimefromaiowebsocket.conversesimportAioWebSocketasyncdefstartup(uri):asyncwithAioWebSocket(uri)asaws:converse=aws.manipulatormessage=b'AioWebSocket-AsyncWebSocketClient'whileTrue:awaitconverse.send(message)print('{time}-Clientsend:{message}'.format(time=datetime.now().strftime('%Y-%m-%d%H:%M:%S'),message=message))mes=awaitconverse.receive()print('{time}-Clientreceive:{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))exceptKeyboardInterruptasexc:logging.info('Quit.')

运行后的结果输出为:

2019-03-0715:43:55-Clientsend:b'AioWebSocket-AsyncWebSocketClient'2019-03-0715:43:55-Clientreceive:b'AioWebSocket-AsyncWebSocketClient'2019-03-0715:43:55-Clientsend:b'AioWebSocket-AsyncWebSocketClient'2019-03-0715:43:56-Clientreceive:b'AioWebSocket-AsyncWebSocketClient'2019-03-0715:43:56-Clientsend:b'AioWebSocket-AsyncWebSocketClient'……

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

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

五、编码获取数据

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

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

importasyncioimportloggingfromdatetimeimportdatetimefromaiowebsocket.conversesimportAioWebSocketasyncdefstartup(uri):asyncwithAioWebSocket(uri)asaws:converse=aws.manipulatorwhileTrue:mes=awaitconverse.receive()print('{time}-Clientreceive:{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))exceptKeyboardInterruptasexc:logging.info('Quit.')

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

这是为什么呢?

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

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

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

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

importasyncioimportloggingfromdatetimeimportdatetimefromaiowebsocket.conversesimportAioWebSocketasyncdefstartup(uri):asyncwithAioWebSocket(uri)asaws:converse=aws.manipulatorwhileTrue:mes=awaitconverse.receive()print('{time}-Clientreceive:{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))exceptKeyboardInterruptasexc:logging.info('Quit.')

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

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

aiowebsocket 做了什么

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

首先,aiowebsocket 根据 WebSocket 地址,向指定的服务端发送握手请求,并校验握手结果。

然后,在确认握手成功后,将数据发送给服务端。

整个过程中为了保持连接不断开,aiowebsocket 会自动与服务端响应 ping pong。

最后,aiowebsocket 读取服务端推送的消息

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Web
    Web
    +关注

    关注

    2

    文章

    1263

    浏览量

    69470
  • python
    +关注

    关注

    56

    文章

    4797

    浏览量

    84689
  • WebSocket
    +关注

    关注

    0

    文章

    29

    浏览量

    3748

原文标题:Python如何爬取实时变化的WebSocket数据

文章出处:【微信号:rgznai100,微信公众号:rgznai100】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    python实现网页爬虫图片

    来实现这样一个简单的爬虫功能,把我们想要的代码取到本地,功能有点类似我们之前学过的批处理。下面就看看如何使用python来实现这样一个功能,主要分为三步,如下:一. 获取整个页面数据首先我们可以先
    发表于 04-05 15:32

    Python爬虫与Web开发库盘点

    Python爬虫和Web开发均是与网页相关的知识技能,无论是自己搭建的网站还是爬虫去别人的网站,都离不开相应的Python库,以下是常用的Python爬虫与Web开发库。1.爬虫库
    发表于 05-10 15:21

    python

    python学习1.数据2.图片
    发表于 09-21 18:18

    采用xpath网站内容

    xpathmooc网课程
    发表于 04-11 12:01

    基于Python3对携程网页上北京五星级酒店列表的

    Python3 携程网[1] 根据好评优先顺序,获取北京五星级酒店列表
    发表于 04-19 16:25

    基于Python实现一只小爬虫拉勾网职位信息的方法

    通俗易懂的分析如何用Python实现一只小爬虫,拉勾网的职位信息
    发表于 05-17 06:54

    python音频文件的步骤

    python爬虫音频文件
    发表于 08-22 14:23

    Python豆瓣电影信息和存储数据

    Python——豆瓣电影信息并存储数据
    发表于 03-11 11:19

    0基础入门Python爬虫实战课

    ,爬虫功不可没。通过爬虫,可以从知乎、微博热门话题,筛选优质答案,分析用户偏好;从淘宝、京东商品、评论及销量数据,分析用户消费场景;
    发表于 07-25 09:28

    python基础语法及流程控制

    爬虫复习1.python基础python基础语法 流程控制 函数封装2.防措施整体防User-AgentrefererIP代理池Cookie代理池 各自防
    发表于 08-31 07:41

    豆瓣电影Top250信息

    ) # 判断是否取到数据,并调用解析函数 if html:for item in parsePage(html):writeFile(item)# 判断当前执行是否为主程序运行,并遍历调用主函数
    发表于 03-23 15:47

    Python CSDN的极客头条

    Python 如何CSDN的极客头条呢?
    的头像 发表于 03-21 14:58 4834次阅读
    <b class='flag-5'>Python</b> <b class='flag-5'>爬</b><b class='flag-5'>取</b>CSDN的极客头条

    如何使用Scrapy网站数据

    网页抓取的主要目标是从无结构的来源提取出结构信息。Scrapy爬虫以Python字典的形式返回提取数据。尽管Python字典既方便又熟悉,但仍然不够结构化:字段名容易出现拼写错误,返回不一致的信息,特别是在有多个爬虫的大型项目中
    的头像 发表于 07-26 09:06 5178次阅读

    如何用python抖音app数据

    记录一下如何用pythonapp数据,本文以抖音视频app为例。
    的头像 发表于 03-16 09:07 5339次阅读

    Scrapy怎么Python文件

    我们介绍了Scrapy框架运行基本原理,紧接着我们介绍了如何利用Scrapy文本数据
    的头像 发表于 02-24 15:16 601次阅读
    Scrapy怎么<b class='flag-5'>爬</b><b class='flag-5'>取</b><b class='flag-5'>Python</b>文件