解码 websocket 收到的数据

decode websocket received data

我正在做我自己网站的项目,我需要使用 websocket 从目标站点抓取数据。 数据是货币和股票价格变动的实时馈送或报价。 我得到以下格式的输出。

试穿 http://websocket.org/echo.html:

地点:wss://streamer.finance.yahoo.com/

单击“连接”。

留言:{"subscribe":["AMZN"]}

输出:

CONNECTED

SENT: {"subscribe":["AMZN"]}

RECEIVED: CgRBTVpOFaQY3EQY4Kn0/99bKgNOTVMwCDgBRYjKzDxIyvN9ZQBQ4T7YAQQ=

RECEIVED: CgRBTVpOFaQY3EQY4Kn0/99bKgNOTVMwCDgBRYnKzDxIzPV9ZQBQ4T7YAQQ=

RECEIVED: CgRBTVpOFT0a3EQYsLn0/99bKgNOTVMwCDgBRYMG5DxIkP99ZQDg+j7YAQQ=

RECEIVED: CgRBTVpOFQAY3EQYwIf1/99bKgNOTVMwCDgBRYd5wzxIxod+ZQAQ1z7YAQQ=

RECEIVED: CgRBTVpOFQAY3EQYwIf1/99bKgNOTVMwCDgBRYd5wzxIroh+ZQAQ1z7YAQQ=

RECEIVED: CgRBTVpOFRQS3EQY8PT1/99bKgNOTVMwCDgBRYC1WjxIhI5+ZQCgcD7YAQQ=

RECEIVED: CgRBTVpOFRQS3EQY8PT1/99bKgNOTVMwCDgBRYG1WjxImo5+ZQCgcD7YAQQ=

RECEIVED: CgRBTVpOFUgN3EQY4KP2/99bKgNOTVMwCDgBRSBhnjtIvpJ+ZQBArj3YAQQ=

RECEIVED: CgRBTVpOFUgN3EQY4KP2/99bKgNOTVMwCDgBRSBhnjtI9J1+ZQBArj3YAQQ=

RECEIVED: CgRBTVpOFUgN3EQY4KP2/99bKgNOTVMwCDgBRSBhnjtIsqR+ZQBArj3YAQQ=

RECEIVED: CgRBTVpOFUgN3EQY4KP2/99bKgNOTVMwCDgBRSBhnjtInq5+ZQBArj3YAQQ=

我不知道如何解码或它是什么类型的加密。 谁能告诉我如何解码它的 encode/decode 类型是什么? 我将使用 PHP 进行解码(如果解码可行)。

I looked into that. I have no clue what to do for understand work flow and debug the function. JS is not my strong suite.

当您连接使用 protobuf 的外部系统时,您不会受制于任何特定语言。 Protobuf 是一种开放技术,当消息的元描述已知时,它允许自动为多种语言创建编组代码。 因此不需要重新使用可用代码,而是从中提取 Protobuf 结构。 Protobuf 编译器将为您完成所有脏工作。

您只需查看 __finStreamer-proto.js 文件即可轻松重建原型文件

PricingData.proto

syntax = "proto3";

message PricingData {

enum QuoteType {
    NONE = 0;
    ALTSYMBOL = 5;
    HEARTBEAT = 7;
    EQUITY = 8;
    INDEX = 9;
    MUTUALFUND = 11;
    MONEYMARKET = 12;
    OPTION = 13;
    CURRENCY = 14;
    WARRANT = 15;
    BOND = 17;
    FUTURE = 18;
    ETF = 20;
    COMMODITY = 23;
    ECNQUOTE = 28;
    CRYPTOCURRENCY = 41;
    INDICATOR = 42;
    INDUSTRY = 1000;
};

enum OptionType {
    CALL = 0;
    PUT = 1;
};

enum MarketHoursType {
    PRE_MARKET = 0;
    REGULAR_MARKET = 1;
    POST_MARKET = 2;
    EXTENDED_HOURS_MARKET = 3;
};

    string id = 1;
    float price = 2;
    sint64 time = 3;
    string currency = 4;
    string exchange = 5;


    QuoteType quoteType = 6;
    MarketHoursType marketHours = 7;
    float changePercent = 8;
    sint64 dayVolume = 9;
    float dayHigh = 10;
    float dayLow = 11;
    float change = 12;
    string shortName = 13;
    sint64 expireDate = 14;
    float openPrice = 15;
    float previousClose = 16;
    float strikePrice = 17;
    string underlyingSymbol = 18;
    sint64 openInterest = 19;
    OptionType optionsType = 20;
    sint64 miniOption = 21;
    sint64 lastSize = 22;
    float bid = 23;
    sint64 bidSize = 24;
    float ask = 25;
    sint64 askSize = 26;
    sint64 priceHint = 27;
    sint64 vol_24hr = 28;
    sint64 volAllCurrencies = 29;
    string fromcurrency = 30;
    string lastMarket = 31;
    double circulatingSupply = 32;
    double marketcap = 33;
};

然后您可以使用 protobuf 编译器从中构建 php 个文件:

mkdir yahoo
protoc --php-out=yahoo PricingData.proto

还有我们的composer.json

{
    "require": {
        "google/protobuf": "^3.11",
        "ratchet/pawl": "^0.3.4"
    },
    "autoload": {
        "classmap": [
            "yahoo"
        ]
    }
}

和php文件吸取数据:

#!/usr/bin/php
<?php

require __DIR__ . '/vendor/autoload.php';

    \Ratchet\Client\connect('wss://streamer.finance.yahoo.com:443')->then(function($conn) {
        $conn->on('message', function($msg) use ($conn) {
            echo "Received: {$msg}\n";
        $packed = base64_decode($msg);
        $msg = new PricingData();
        $msg->mergeFromString($packed);
        var_dump($msg->serializeToJsonString());
        });

    $conn->send('{"subscribe":["BTC-USD","ETH-USD","XRP-USD","USDT-USD","BCH-USD","BA","TSLA","AXSM","UBER","MIRM","GRKZF","SCGPY","BDVSF","WPX","BIPSX","ENPIX","ENPSX","BPTUX","BPTIX","CL=F","GC=F","SI=F","EURUSD=X","GBPUSD=X","JPY=X","EZA","IXC","IYE","FILL","EWT","CGIX1191220P00005000","TORC191220P00002500","RIOT191213C00001000","TPCO191220C00002500","DHR","AMRN","AMD","PCG","VIX191218P00012500","VIX191218P00014000","EEM191220P00039000","EEM200117C00045000","BTCUSD=X","ETHUSD=X","AUDUSD=X","NZDUSD=X","EURJPY=X","GBPJPY=X","EURGBP=X","EURCAD=X","EURSEK=X","EURCHF=X","EURHUF=X","CNY=X","HKD=X","SGD=X","INR=X","MXN=X","PHP=X","IDR=X","THB=X","MYR=X","ZAR=X","RUB=X","ZG=F","ZI=F","PL=F","HG=F","PA=F","HO=F","NG=F","RB=F","BZ=F","B0=F","C=F","O=F","KW=F","RR=F","SM=F","BO=F","S=F","FC=F","LH=F","LC=F","CC=F","KC=F","CT=F","LB=F","OJ=F","SB=F","IFF","CRS","RLLCF","BGNE","^GSPC","^DJI","^IXIC","^RUT","^TNX","^VIX","^CMC200","^FTSE","^N225"]}');

    }, function ($e) {
        echo "Could not connect: {$e->getMessage()}\n";
    });

并且....我们开始:

Received: CgNQQ0cVH4UvQRiQvr/a4lsqA05ZUTAIOAFFKBlXQUj61YQeZWhmpj/YAQQ=
string(202) "{"id":"PCG","price":10.97,"time":"1576616325000","exchange":"NYQ","quoteType":"EQUITY","marketHours":"REGULAR_MARKET","changePercent":13.443642,"dayVolume":"31495549","change":1.3000002,"priceHint":"2"}"
Received: CghFVVJHQlA9WBW6a1k/GODNv9riWyoDQ0NZMA44AUV+6bc/ZYAZRTzYAQg=
string(193) "{"id":"EURGBP=X","price":0.84930003,"time":"1576616326000","exchange":"CCY","quoteType":"CURRENCY","marketHours":"REGULAR_MARKET","changePercent":1.4368131,"change":0.012030005,"priceHint":"4"}"
Received: CghHQlBKUFk9WBVxvQ9DGODNv9riWyoDQ0NZMA44AUUQl7S/ZcClA8DYAQg=
string(192) "{"id":"GBPJPY=X","price":143.74001,"time":"1576616326000","exchange":"CCY","quoteType":"CURRENCY","marketHours":"REGULAR_MARKET","changePercent":-1.4108601,"change":-2.0569916,"priceHint":"4"}"
Received: CgVNWE49WBWqgpdBGJC+v9riWyoDQ0NZMA44AUXYFZ89ZQDYcDzYAQg=
string(191) "{"id":"MXN=X","price":18.938801,"time":"1576616325000","exchange":"CCY","quoteType":"CURRENCY","marketHours":"REGULAR_MARKET","changePercent":0.077678382,"change":0.014699936,"priceHint":"4"}"
Received: CgVTR0Q9WBWCi60/GJC+v9riWyoDQ0NZMA44AUXWfb49ZQAkpTq9AX6MrT/NAXGPrT/YAQg=
string(219) "{"id":"SGD=X","price":1.3558199,"time":"1576616325000","exchange":"CCY","quoteType":"CURRENCY","marketHours":"REGULAR_MARKET","changePercent":0.093013451,"change":0.001259923,"bid":1.35585,"ask":1.35594,"priceHint":"4"}"
Received: CgVKUFk9WBVQDdtCGODNv9riWyoDQ0NZMA44AUW/HUa9ZQAYWb3YAQg=
string(191) "{"id":"JPY=X","price":109.526,"time":"1576616326000","exchange":"CCY","quoteType":"CURRENCY","marketHours":"REGULAR_MARKET","changePercent":-0.048368212,"change":-0.053001404,"priceHint":"4"}"
Received: CgRVQkVSFZqZ7UEY4M2/2uJbKgNOWVEwCDgBRY8Vlb9IxqSRHGUAM7O+2AEE
string(210) "{"id":"UBER","price":29.700001,"time":"1576616326000","exchange":"NYQ","quoteType":"EQUITY","marketHours":"REGULAR_MARKET","changePercent":-1.1647204,"dayVolume":"29501731","change":-0.34999847,"priceHint":"2"}"
Received: CgRUU0xBFR9lvUMYwK6/2uJbKgNOTVMwCDgBRZvZNb9IoL/SB2WAcC3A2AEE
string(209) "{"id":"TSLA","price":378.79001,"time":"1576616324000","exchange":"NMS","quoteType":"EQUITY","marketHours":"REGULAR_MARKET","changePercent":-0.71035165,"dayVolume":"8015824","change":-2.7099915,"priceHint":"2"}"
Received: CghFVVJHQlA9WBXLZ1k/GLDdv9riWyoDQ0NZMA44AUWW/rY/ZcAdRDzYAQg=
string(193) "{"id":"EURGBP=X","price":0.84924001,"time":"1576616327000","exchange":"CCY","quoteType":"CURRENCY","marketHours":"REGULAR_MARKET","changePercent":1.4296443,"change":0.011969984,"priceHint":"4"}

如你所见,protobuf 是一个很棒的东西,它与语言无关,所以你不必应付一些不熟悉的语言

可以使用或参考my repository(感谢Maxim提供原型文件!)。

它易于使用 Python package

  1. 安装包
    pip install yliveticker
  1. 使用以下代码创建livemarket.py文件
    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"])
  1. 运行代码
    python livemarket.py
  1. 观看控制台输出中出现的实时市场数据。

如果您没有看到任何结果,请确保您在您的证券交易所 trading hours 范围内

感谢@Maxim,我能够更好地理解它的工作原理并制作了它的 NodeJS 版本。

这是基本示例的代码,我将花一些时间基于 Electron 为其构建动态订阅和最终应用程序。这个想法是获取解码数据并推送到本地 SocketIO 服务器,在那里它可以在不同的应用程序中与 VueJS 一起使用。

const WebSocket = require('ws')
var ProtoBuf = require("protobufjs");

"use strict";
let Message = ProtoBuf
.loadProtoFile('./PricingData.proto', (err, builder)=>{
    Message = builder.build('PricingData')
    loadMessage()
})



let loadMessage = ()=> {
    const url = 'wss://streamer.finance.yahoo.com'
    const connection = new WebSocket(url)
    connection.onopen = () => {
    connection.send('{"subscribe":["TSLA","AXSM","UBER","MIRM","GRKZF","BTCUSD=X","ETHUSD=X","AUDUSD=X","^DJI","^IXIC","^RUT","^TNX","^VIX","^CMC200","^FTSE","^N225"]}') 
    }

    connection.onerror = (error) => {
    console.log(`WebSocket error: ${error}`)
    }

    connection.onmessage = (e) => {
    let msg = Message.decode(e.data)
    console.log('Decoded message', msg)
    }
}

更新快: 这是我的回购协议中的完整示例 https://github.com/markosole/yahoo-node-streamer