Python爬取WebSocket数据 - 初尝试

参考链接:

WebSocket 通信原理【底层】:原来你是这样的Websocket–抓包分析
Python 爬取 WebSocket【顶层】:Python如何爬取实时变化的WebSocket数据的方法

注意:可以直接参考上述链接,解释地很详细。

WebSocket 爬虫

目录

1. WebSocket 介绍
2. 分析
3. 编写爬序
4. 其它
5. 总结

一、WebSocket 介绍 ↶

        WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。【摘自 - 百度百科】
        补充【自己的理解】:客户端发起ws/wss协议链接请求(类似于http/https协议的链接请求),当中会有一次握手(状态码为101则为成功建立)。每次建立后首先由客户端发起消息到服务器,服务器验证返回信息(互相发送信息可能不止一次,才到服务器真正的返回有用的数据。)如下图所示:
Python爬取WebSocket数据 - 初尝试_第1张图片
        上图中,绿色箭头向上是客户端(如浏览器)发送信息给服务器,红色箭头向下是服务器发送信息给客户端。可以看出前面几次信息发送相当于验证过程。

二、分析 ↶

根据参考链接中给出的例子,是一个很好地例子。这里也用这个例子尝试一下。
网站链接:莱特币中国官方网站Litecoin

  1. 网站初始界面
    Python爬取WebSocket数据 - 初尝试_第2张图片

  2. F12开发人员界面,F5刷新
    Python爬取WebSocket数据 - 初尝试_第3张图片

  3. 选择WS选项卡,找到realTime
    Python爬取WebSocket数据 - 初尝试_第4张图片
    从图中,我们找到的信息有:realTime是websocket类型,状态码为101(建立成功)

  4. 点击realTime,查看更多信息
    Python爬取WebSocket数据 - 初尝试_第5张图片
    Python爬取WebSocket数据 - 初尝试_第6张图片

  5. 找到socket链接,可以编写程序【具体原理分析可以看参考链接的第二个】
    socket:wss://api.bbxapp.vip/v1/ifcontract/realTime

三、编写爬虫 ↶

代码 copy 来的,这些 Python代码 不太熟:

import asyncio #异步
import logging # 日志
from datetime import datetime #时间
from aiowebsocket.converses import AioWebSocket #aiowebsocket需要安装,异步websocket


async def startup(uri): # anync 异步语法
    async with AioWebSocket(uri) as aws:
        converse = aws.manipulator
        # 客户端给服务端发送消息
        await converse.send('{"action":"subscribe","args":["QuoteBin5m:14"]}') # await 也是异步语法
        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.')

解释:

当中最重要的是一句是:
await converse.send('{"action":"subscribe","args":["QuoteBin5m:14"]}')
这相当于下图验证的过程:

对应查看,直到客户端发送此条信息,服务器才源源不断地发送信息:
Python爬取WebSocket数据 - 初尝试_第7张图片
最终运行效果图:
Python爬取WebSocket数据 - 初尝试_第8张图片

四、其它 ↶

1.抓包任务可以由Fiddler代替,Fiddler也可以抓到WebSocket

红色的就是websocket,可以看到状态码为101,建立成功
在这里插入图片描述
细节查看(与浏览器基本一致,可能有人说浏览器也可以做到,要Fiddler有什么用,这就可以体现出作为强大抓包软件的性能,Fiddler可以轻松地抓到手机包,要是手机app用websocket通信不就可以抓取了):
Python爬取WebSocket数据 - 初尝试_第9张图片
添加Fiddler日志,查看详细细节:
(1) 在菜单栏中,打开Rules - Customize Rules
Python爬取WebSocket数据 - 初尝试_第10张图片
Python爬取WebSocket数据 - 初尝试_第11张图片
(2)添加一下代码到上述窗口中的 class Handlers里

static function OnWebSocketMessage(oMsg: WebSocketMessage) {
        // Log Message to the LOG tab
        FiddlerApplication.Log.LogString(oMsg.ToString());
    } 

(3)添加结果,保存
Python爬取WebSocket数据 - 初尝试_第12张图片
(4)效果【出现关于websocket更详细地日志】
Python爬取WebSocket数据 - 初尝试_第13张图片

2. 客户端发送信息验证问题 - 聊天室(2probe/3probe)

相关链接:使用jmeter对websocket进行压力测试
还记得有时候需要发送一些数据验证,服务器才会不断发送数据。之前遇到一个问题,就是客户端上传2probe给服务器,所以思考一个问题,2probe是什么?为什么要2probe?难受啊 我天?
后来查找资料的时候发现,就把它当成一段数据(字符串)发送给服务器就可以。
如:

await converse.send('2probe')

注意:客户端可能不是仅仅发送一条2probe数据,服务器就开始返还所需数据,可能还需要继续发送,所要做就是模拟客户端发送/接受的过程即可:
如:

await converse.send('2probe')
mes = await converse.receive()
await converse.send('2')
mes = await converse.receive()
.
.
.
mes = await converse.receive() # 直到收到正确的数据
3. 遇到 python UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 1-1: Non-BMP character怎么办?

解决方案:‘UCS-2’ codec can’t encode characters in position 1050-1050

import sys
non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd)
print(x.translate(non_bmp_map))

注意:x是字符串,替换为想要解决问题的地方

五、总结 ↶

        主要写了Python爬取WebSocket的初尝试,因为对WebSocket还不是很了解,而且异步编程还没有学会,虽然语法很简单,但是怎么看怎么变扭。我觉得很多东西,都是上手简单,理解难,看的多了自然就通了。如同当初刚开始接触Python的类编写的时候,真的非常痛苦,完全无法理解为什么要这么写,或者说为什么我写的不通过,他写地就通过了。难受啊。虽然无法理解,但是我一直看、写,总算是理解一部分。后来,读了《Learning Python 5th Edition》这本书后,我终于可以理解类为什么这么写。实例和类本身的关系【继承树概念的形成很重要】。好吧,扯远了。
        好吧,让我们一起加油吧!ヾ(◍°∇°◍)ノ゙

点我回顶部 ☚

 
 
 
 
 
 
 
Fin.

你可能感兴趣的:(我的爬虫之旅)