Python web-socket解释(读取)数据

Posted

技术标签:

【中文标题】Python web-socket解释(读取)数据【英文标题】:Python web-socket interpreting(reading) Data 【发布时间】:2019-10-10 19:41:49 【问题描述】:

尝试试验并了解有关用于网络抓取的套接字的更多信息。

我正在尝试通过 WebSockets 从网站流式传输信息。我能够接收数据,但想知道从它读取和解释传入数据的正确方法是什么。

我正在使用 Python 3.7。我能够使用来自https://towardsdatascience.com/scraping-in-another-dimension-7c6890a156da 的示例建立连接 我正在尝试通过套接字在https://finance.yahoo.com/quote/BTC-USD/chart 上显示一些股票价格数据。 这是我正在使用的代码:

import websocket
import json
from websocket import create_connection


headers = json.dumps(
    'Accept-Encoding':'gzip deflat,br',
    'Accept-Language':'en-US,en;q=0.9,zh-TW;q=0.8,zh;q=0.7,zh-CN;q=0.6',
    'Cache-Control': 'no-cache',
    'Connection': 'Upgrade',

    'Host': 'streamer.finance.yahoo.com',
    'Origin': 'https://finance.yahoo.com',
    'Pragma': 'no-cache',
    'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
    'Sec-WebSocket-Key': 'VW2m4Lw2Rz2nXaWO10kxhw==',
    'Sec-WebSocket-Version': '13',
    'Upgrade': 'websocket',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
    )

ws = create_connection('wss://streamer.finance.yahoo.com/',headers=headers)

ws.send('"subscribe":["^GSPC","^DJI","^IXIC","^RUT","CL=F","GC=F","SI=F","EURUSD=X","^TNX","^VIX","GBPUSD=X","JPY=X","BTC-USD","^FTSE","^N225"]')


while True:
    result  = ws.recv()
    print(result)

ws.close()

这让我得到这样的结果:

CgReREpJFebCzkYYwJHv8LZbKgNESkkwCTgBRWYd6D5I7tDaigFlAOHuQtgBBA==
CgVKUFk9WBUX2ddCGMCR7/C2WyoDQ0NZMA44AUUVH9w+ZQCM7D7YAQg=
CghFVVJVU0Q9WBVA2Yw/GMCR7/C2WyoDQ0NZMA44AUXuDJI+ZQAgTTvYAQg=
CghHQlBVU0Q9WBUQO58/GMCR7/C2WyoDQ0NZMA44AUXz/fY/ZcDrwDzYAQg=
CgReVklYFYXrkUEYgKOB8LZbKgNXQ0IwCTgBRcRWCcBlwMzMvtgBBA==
CghHQlBVU0Q9WBUVOp8/GJCh7/C2WyoDQ0NZMA44AUWcrfY/ZQCtwDzYAQg=
CgVKUFk9WBUv3ddCGJCh7/C2WyoDQ0NZMA44AUVQ7t8+ZQCk8D7YAQg=
CghFVVJVU0Q9WBU424w/GJCh7/C2WyoDQ0NZMA44AUWi2pQ+ZQAQUTvYAQg=

不知道如何解释我收到的数据,或者网络浏览器如何解释这些数据。似乎浏览器正在接收与我相同的数据。

【问题讨论】:

嗯,这显然是 Base64 编码的数据(大多数行末尾的单等号和双等号是一个死的赠品)。 Python 有一个解码它的模块,但是你必须解释生成的二进制数据——我快速浏览了一下,但它没有任何明显的格式。希望如果雅虎允许您直接检索这些数据,那么他们还会在某处记录其格式...... 【参考方案1】:

我猜这是 Protobuf 编码的数据。通过查看 yahoo Finance 页面的 javascript 源代码,您可以看到,一旦订阅了代码,回复就会由解码例程处理。

https://finance.yahoo.com/__finStreamer-worker.js

... 在接下来的 sn-p 中,有一个从 base64 文本到字节然后到 Javascript 对象(PricingData 类型)的明确转换。注意提到 protobuf。

QuoteStreamer.prototype.handleWebSocketUpdate = function (event) 
    try 
        var PricingData = protobuf.roots.default.quotefeeder.PricingData;
        var buffer = base64ToArray(event.data); // decode from base 64
        var data = PricingData.decode(buffer); // Decode using protobuff
        data = PricingData.toObject(data,  // Convert to a JS object
            enums: String
        );

接下来您需要弄清楚 Yahoo 使用的 Protobuf 架构(然后您可以使用 Python 生成解码器),但我不确定它是否公开。但是,您可以检查他们生成的用于执行解码的实际 Protobuf Javascript 代码,并尝试直接在 Python 中复制它,或者猜测 protobuf 架构。

Javascript 解码器在这里:https://finance.yahoo.com/__finStreamer-proto.js

【讨论】:

【参考方案2】:

这确实是一个 protobuf 编码的数据。马克西姆could compose a protobuf file from it.

我创建了一个 python package 来完成它。你需要做的就是

    安装它
    pip install yliveticker
    导入并获取解码结果
    import yliveticker


    # this function is called on each ticker update
    def on_new_msg(msg):
        print(msg)


    # insert your symbols here
    yliveticker.YLiveTicker(on_ticker=on_new_msg, ticker_names=[
    "BTC=X", "^GSPC", "^DJI", "^IXIC", "^RUT", "CL=F", "GC=F", "SI=F", "EURUSD=X", "^TNX", "^VIX", "GBPUSD=X", "JPY=X", "BTC-USD", "^CMC200", "^FTSE", "^N225"])

随意贡献或使用存储库作为您项目的示例;)

如果您没有看到任何数据,请检查您是否使用trading hours of your stock exchange。

【讨论】:

以上是关于Python web-socket解释(读取)数据的主要内容,如果未能解决你的问题,请参考以下文章

使用一个 pyaudio 流进行数据读取和写入

python web-socket客户端这个日志来自哪里?

django Web-Sockets 设计和内存数据存储

设计/架构:web-socket 单连接 vs 多连接

web-socket 客户端不会连接到 API

在没有弹簧身份验证的情况下通过 web-socket 多次回复