2017-10-04 2 views
3

J'essaie de me connecter au flux websocket de Cryptocompare en utilisant socketIO à partir d'un client Python. Cela s'avère difficile. Voici quelques exemples de code Python:Exemple de Python socketio pour se connecter à cryptocompare

from socketIO_client import SocketIO 

print "connecting to server" 
socketIO = SocketIO('https://streamer.cryptocompare.com/',443, transports=['websocket']) 
print "Connected" 

Cependant, je ne peux pas me connecter, quoi que je fasse. En fait, cela est le résultat de ce connecter

connecting to server 
Traceback (most recent call last): 
    File "test.py", line 4, in <module> 
socketIO = SocketIO('https://streamer.cryptocompare.com/',443, transports=['websocket']) 
    File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 353, in __init__ 
resource, hurry_interval_in_seconds, **kw) 
    File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 54, in __init__ 
self._transport 
    File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 62, in _transport 
self._engineIO_session = self._get_engineIO_session() 
    File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 76, in _get_engineIO_session 
transport.recv_packet()) 
StopIteration 

Envelopper les rendements d'exception code ci-dessus dans un try-catch et l'impression d'aucune information supplémentaire. Toute aide serait grandement appréciée.

+0

problème peut être serveur dégrossi que je suis incapable d'établir une connexion (même en frappant leur serveur directement avec 'websocket.connect ('WSS : //streamer.cryptocompare.com/socket.io/websocket ') '). – rob

+0

A noter également, lors de l'utilisation du [client JavaScript] (https://github.com/cryptoqween/cryptoqween.github.io/blob/master/streamer/current/stream.js#L68) il se connecte sans erreur – rob

+0

Oui , cependant je pense que notre problème est le manque de bon exemple. Il semblerait que l'implémentation de websockets et de socketio par Python soit un véritable casse-tête. –

Répondre

0

Vous devez appeler Emit juste après avoir configuré le socket pour configurer les abonnements que vous souhaitez recevoir.

socketIO.emit('SubAdd', { subs: ['0~Poloniex~BTC~USD'] }); 
+0

Mais il renvoie 401 ~ BADFORMAT ... Toute aide à ce sujet? –

0

J'ai regardé ce problème de quelques angles et a conclu que le client socketio pour python ne fonctionne pas avec cette API. Si vous voulez simplement streamer des données vers python à partir de l'api de streaming CryptoCompare, j'ai une solution de contournement qui utilise websockets pour envoyer des requêtes à une simple application nodejs qui utilise ensuite son client socketio pour streamer les données requises. Je suis assez nouveau sur python et je viens juste de regarder nodejs pour cette solution alors allez-y doucement sur moi.

Crypto est chaud en ce moment donc je suis sûr que ce sera utile à certains

La partie Python:

import json 
import pandas as pd 
try: 
    import thread 
except ImportError: 
import _thread as thread 

import threading 
import time 
import websocket 


class WebSocketClient(threading.Thread): 

def __init__(self): 
    self.url = 'ws://localhost:9030/path' 
    # self.daemon = True 
    self.clist = list() 
    threading.Thread.__init__(self) 


def run(self): 

    # Running the run_forever() in a seperate thread. 
    #websocket.enableTrace(True) 
    self.ws = websocket.WebSocketApp(self.url, 
            on_message = self.on_message, 
            on_error = self.on_error, 
            on_close = self.on_close) 
    self.ws.on_open = self.on_open 
    self.ws.run_forever() 

def send(self, data): 

    data = self._encode_message(data) 
    # Wait till websocket is connected. 
    while not self.ws.sock.connected: 
     time.sleep(0.25) 

    print(f'Sending data... {data}') 
    self.ws.send(data) 

def stop(self): 
    print(f'Stopping the websocket...') 
    self.ws.close() 

def on_message(self, ws, message): 
    message = self._decode_message(message) 
    print(f'Received data...{message}') 
    if message['msg']=='crypto': 

     self.clist.append(message['data']) 

def on_error(self, ws, error): 
    print(f'Received error...') 
    print(error) 

def on_close(self, ws): 
    print('Closed the connection...') 

def on_open(self, ws): 
    print('Opened the connection...') 
    data = {"msg":"open" ,"from":"Rob", "data":"Hello from the client"} 
    self.send(data) 

def _encode_message(self,message): 

    message = json.dumps(message) 
    return message 

def _decode_message(self, message): 

    message = json.loads(message) 
    return message 

def getclist(self): 
    return self.clist 


wsCli = WebSocketClient() 
wsCli.daemon = True 
wsCli.start() 
wsCli.send({"msg":"getcrypto" ,"from":"Client", "data":['0~Coinbase~BTC~USD'],"subs":['0~Coinbase~BTC~USD']}) 
wsCli.stop() 

La NodeJS partie:

var socket = require('socket.io-client')('https://streamer.cryptocompare.com/') 
 
var socketon = false 
 

 
var WebSocketServer = require('ws').Server , wss = new WebSocketServer({port: 9030}); 
 
wss.on('connection', function(ws) { 
 
     ws.on('message', function(message) { 
 
\t \t \t   msg = decode_message(message); 
 
         console.log('received: %s', message); 
 
         console.log('test: %s', msg['msg']); 
 
\t \t \t \t \t \t \t switch(msg['msg']) { 
 
\t \t \t \t \t \t \t \t case 'open': 
 
             message_type = 'open'; 
 
\t \t \t \t \t \t \t \t \t  
 
\t 
 
\t \t \t \t \t \t \t \t \t // do something with chat data. i.e.: 
 
\t \t \t \t \t \t \t \t \t console.log("open from " + msg['from'] + 
 
\t \t \t \t \t \t \t \t \t \t ": " + msg['data']); 
 
\t \t \t \t \t \t \t \t \t 
 
            outmessage = 'welcome from server ' + msg['from']; 
 
\t \t \t \t \t \t \t \t \t ws.send(encode_message(outmessage, message_type = 'open')); 
 
\t \t \t \t \t \t \t \t \t break 
 
\t \t \t \t \t \t \t \t case 'getcrypto': 
 
\t \t \t \t \t \t \t \t \t message_type = "crypto" 
 
\t \t \t \t \t \t \t \t \t // do something with chat data. i.e.: 
 
\t \t \t \t \t \t \t \t \t console.log("'getcrypto': object" + msg['data']); 
 
            socket.emit('SubAdd', { subs: msg.subs }); 
 
            if (!socketon) { 
 
             socket.on("m", function (message) { 
 
              var messageType = message.substring(0, message.indexOf("~")); 
 
              var res = {}; 
 
              switch (messageType) { 
 
               case CCC.STATIC.TYPE.TRADE: 
 
                res = CCC.TRADE.unpack(message); 
 
                break; 
 
               case CCC.STATIC.TYPE.CURRENT: 
 
                res = CCC.CURRENT.unpack(message); 
 
                break; 
 
               case CCC.STATIC.TYPE.CURRENTAGG: 
 
                res = CCC.CURRENT.unpack(message); 
 
                // updateQuote(res); 
 
                break; 
 
               case CCC.STATIC.TYPE.ORDERBOOK: 
 
                res = CCC.ORDER.unpack(message); 
 
                break; 
 
               case CCC.STATIC.TYPE.FULLORDERBOOK: 
 
                res = CCC.ORDER.unpack(message); 
 
                break; 
 
              } 
 
              console.log(message); 
 
              console.log(res); 
 
              ws.send(encode_message(res, message_type = "crypto")); 
 
             }) 
 
            } 
 
            socketon = true; 
 
\t \t \t \t \t \t \t \t \t break 
 
\t \t \t \t \t \t \t \t case 'canccrypto': 
 
\t \t \t \t \t \t \t \t \t // do something with chat data. i.e.: 
 
\t \t \t \t \t \t \t \t \t message_type = "crypto" 
 
\t \t \t \t \t \t \t \t \t console.log(msg['msg'] +":" + msg['data']); 
 
\t \t \t \t \t \t \t \t \t socket.emit('SubRemove', { subs: msg.subs }); 
 
\t \t \t \t \t \t \t \t \t break 
 
\t \t \t \t \t \t \t \t case 'other': 
 
\t \t \t \t \t \t \t \t \t // do something with chat data. i.e.: 
 
\t \t \t \t \t \t \t \t \t  
 
\t \t \t \t \t \t \t \t \t console.log("open from " + msg['from'] + 
 
\t \t \t \t \t \t \t \t \t \t ": " + msg['data']); 
 
\t \t \t \t \t \t \t \t \t outmessage = 'other from server ' + msg['from'] 
 
\t \t \t \t \t \t \t \t \t ws.send(encode_message(outmessage, message_type = "other")); 
 
\t \t \t \t \t \t \t \t \t break 
 
\t \t \t \t \t \t \t \t // ... and so on 
 
\t \t \t \t \t \t \t } 
 
      }); 
 

 
    }); 
 

 
function decode_message(message) { 
 
\t msg = JSON.parse(message); 
 
\t return msg; 
 
} 
 

 
function encode_message(message, messsage_type) { 
 
\t if (message_type == "crypto") { 
 
\t \t var msg_crypto = { 'msg': 'crypto', 'data': message }; 
 
\t \t msg = JSON.stringify(msg_crypto); 
 
\t } 
 
\t else { 
 
\t \t var msg_other = { 'msg': 'other', 'data': message }; 
 
\t \t msg = JSON.stringify(msg_other); 
 
\t } 
 
\t return msg; 
 
} 
 

 

 
var CCC = CCC || {}; 
 

 
CCC.STATIC = CCC.STATIC || {}; 
 

 
CCC.STATIC.TYPE = { 
 
\t 'TRADE': '0' 
 
\t , 'FEEDNEWS': '1' 
 
\t , 'CURRENT': '2' 
 
\t , 'LOADCOMPLATE': '3' 
 
\t , 'COINPAIRS': '4' 
 
\t , 'CURRENTAGG': '5' 
 
\t , 'TOPLIST': '6' 
 
\t , 'TOPLISTCHANGE': '7' 
 
\t , 'ORDERBOOK': '8' 
 
\t , 'FULLORDERBOOK': '9' 
 
\t , 'ACTIVATION': '10' 
 

 
\t , 'TRADECATCHUP': '100' 
 
\t , 'NEWSCATCHUP': '101' 
 

 
\t , 'TRADECATCHUPCOMPLETE': '300' 
 
\t , 'NEWSCATCHUPCOMPLETE': '301' 
 

 
}; 
 

 
CCC.STATIC.CURRENCY = CCC.STATIC.CURRENCY || {}; 
 

 
CCC.STATIC.CURRENCY.SYMBOL = { 
 
\t 'BTC': '?' 
 
\t , 'LTC': '?' 
 
\t , 'DAO': 'Ð' 
 
\t , 'USD': '$' 
 
\t , 'CNY': '¥' 
 
\t , 'EUR': '€' 
 
\t , 'GBP': '£' 
 
\t , 'JPY': '¥' 
 
\t , 'PLN': 'z?' 
 
\t , 'RUB': '?' 
 
\t , 'ETH': '?' 
 
\t , 'GOLD': 'Gold g' 
 
\t , 'INR': '?' 
 
\t , 'BRL': 'R$' 
 
}; 
 

 
CCC.STATIC.CURRENCY.getSymbol = function (symbol) { 
 
\t return CCC.STATIC.CURRENCY.SYMBOL[symbol] || symbol; 
 
}; 
 

 
CCC.STATIC.UTIL = { 
 
\t exchangeNameMapping: { 
 
\t \t 'CCCAGG': 'CryptoCompare Index', 
 
\t \t 'BTCChina': 'BTCC' 
 
\t }, 
 
\t isMobile: function (userAgent) { 
 
\t \t if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm(os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(userAgent) 
 
\t \t \t || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s)|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp(i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac(|\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt(|\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg(g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v)|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v)|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-|)|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4))) 
 
\t \t \t return true; 
 
\t \t return false; 
 
\t }, 
 
\t convertToMB: function (bytes) { 
 
\t \t return (parseInt(bytes, 10)/1024/1024).toFixed(2) + ' MB'; 
 
\t }, 
 
\t getNameForExchange: function (exchangeName) { 
 
\t \t if (this.exchangeNameMapping.hasOwnProperty(exchangeName)) { 
 
\t \t \t return this.exchangeNameMapping[exchangeName]; 
 
\t \t } 
 
\t \t return exchangeName; 
 
\t }, 
 
\t noExponents: function (value) { 
 
\t \t var data = String(value).split(/[eE]/); 
 
\t \t if (data.length == 1) return data[0]; 
 

 
\t \t var z = '', sign = value < 0 ? '-' : '', 
 
\t \t \t str = data[0].replace('.', ''), 
 
\t \t \t mag = Number(data[1]) + 1; 
 

 
\t \t if (mag < 0) { 
 
\t \t \t z = sign + '0.'; 
 
\t \t \t while (mag++) z += '0'; 
 
\t \t \t return z + str.replace(/^\-/, ''); 
 
\t \t } 
 
\t \t mag -= str.length; 
 
\t \t while (mag--) z += '0'; 
 
\t \t return str + z; 
 
\t }, 
 
\t reduceFloatVal: function (value) { 
 
\t \t value = parseFloat(value); 
 
\t \t if (value > 1) { 
 
\t \t \t value = Math.round(value * 100)/100; 
 
\t \t \t return value; 
 
\t \t } 
 
\t \t if (value >= 0.00001000) { 
 
\t \t \t return parseFloat(value.toPrecision(4)); 
 
\t \t } 
 
\t \t if (value >= 0.00000100) { 
 
\t \t \t return parseFloat(value.toPrecision(3)); 
 
\t \t } 
 
\t \t if (value >= 0.00000010) { 
 
\t \t \t return parseFloat(value.toPrecision(2)); 
 
\t \t } 
 
\t \t return parseFloat(value.toPrecision(1)); 
 
\t }, 
 
\t reduceReal: function (value) { 
 
\t \t value = parseFloat(value); 
 
\t \t return parseFloat(value.toFixed(8)); 
 
\t }, 
 
\t convertCurrentKeyToAll: function (key) { 
 
\t \t var valuesArray = key.split("~"); 
 
\t \t valuesArray[0] = CCC.STATIC.TYPE.CURRENTAGG; 
 
\t \t valuesArray[1] = 'CCCAGG'; 
 
\t \t return valuesArray.join('~'); 
 
\t }, 
 
\t convertCurrentKeyToTrade: function (key) { 
 
\t \t var valuesArray = key.split("~"); 
 
\t \t valuesArray[0] = CCC.STATIC.TYPE.TRADE; 
 
\t \t return valuesArray.join('~'); 
 
\t }, 
 
\t convertValueToDisplay: function (symbol, value, filterNumberFunctionAngularJS, type, fullNumbers) { 
 
\t \t var prefix = ''; 
 
\t \t var valueSign = 1; 
 
\t \t value = parseFloat(value); 
 
\t \t var valueAbs = Math.abs(value); 
 
\t \t var decimalsOnBigNumbers = 2; 
 
\t \t var decimalsOnNormalNumbers = 2; 
 
\t \t var decimalsOnSmallNumbers = 4; 
 
\t \t if (fullNumbers === true) { 
 
\t \t \t decimalsOnBigNumbers = 2; 
 
\t \t \t decimalsOnNormalNumbers = 0; 
 
\t \t \t decimalsOnSmallNumbers = 4; 
 
\t \t } 
 
\t \t if (type == "8decimals") { 
 
\t \t \t decimalsOnBigNumbers = 4; 
 
\t \t \t decimalsOnNormalNumbers = 8; 
 
\t \t \t decimalsOnSmallNumbers = 8; 
 
\t \t \t if (value < 0.0001 && value >= 0.00001) { decimalsOnSmallNumbers = 4; } 
 
\t \t \t if (value < 0.001 && value >= 0.0001) { decimalsOnSmallNumbers = 5; } 
 
\t \t \t if (value < 0.01 && value >= 0.001) { decimalsOnSmallNumbers = 6; } 
 
\t \t \t if (value < 0.1 && value >= 0.01) { decimalsOnSmallNumbers = 7; } 
 
\t \t } 
 
\t \t if (symbol != '') { prefix = symbol + ' '; } 
 
\t \t if (value < 0) { valueSign = -1; } 
 
\t \t if (value == 0) { return prefix + '0'; } 
 

 
\t \t if (value < 0.00001000 && value >= 0.00000100 && decimalsOnSmallNumbers > 3) { 
 
\t \t \t decimalsOnSmallNumbers = 3; 
 
\t \t } 
 
\t \t if (value < 0.00000100 && value >= 0.00000010 && decimalsOnSmallNumbers > 2) { 
 
\t \t \t decimalsOnSmallNumbers = 2; 
 
\t \t } 
 
\t \t if (value < 0.00000010 && decimalsOnSmallNumbers > 1) { 
 
\t \t \t decimalsOnSmallNumbers = 1; 
 
\t \t } 
 

 
\t \t if (type == "short" || type == "8decimals") { 
 
\t \t \t if (valueAbs > 10000000000) { 
 
\t \t \t \t valueAbs = valueAbs/1000000000; 
 
\t \t \t \t return prefix + filterNumberFunctionAngularJS(valueSign * valueAbs, decimalsOnBigNumbers) + ' B'; 
 
\t \t \t } 
 
\t \t \t if (valueAbs > 10000000) { 
 
\t \t \t \t valueAbs = valueAbs/1000000; 
 
\t \t \t \t return prefix + filterNumberFunctionAngularJS(valueSign * valueAbs, decimalsOnBigNumbers) + ' M'; 
 
\t \t \t } 
 
\t \t \t if (valueAbs > 10000) { 
 
\t \t \t \t valueAbs = valueAbs/1000; 
 
\t \t \t \t return prefix + filterNumberFunctionAngularJS(valueSign * valueAbs, decimalsOnBigNumbers) + ' K'; 
 
\t \t \t } 
 
\t \t \t if (type == "8decimals" && valueAbs >= 100) { 
 
\t \t \t \t return prefix + filterNumberFunctionAngularJS(valueSign * valueAbs, decimalsOnBigNumbers); 
 
\t \t \t } 
 
\t \t \t if (valueAbs >= 1) { 
 
\t \t \t \t return prefix + filterNumberFunctionAngularJS(valueSign * valueAbs, decimalsOnNormalNumbers); 
 
\t \t \t } 
 
\t \t \t return prefix + (valueSign * valueAbs).toPrecision(decimalsOnSmallNumbers); 
 
\t \t } else { 
 
\t \t \t if (valueAbs >= 1) { 
 
\t \t \t \t return prefix + filterNumberFunctionAngularJS(valueSign * valueAbs, decimalsOnNormalNumbers); 
 
\t \t \t } 
 

 
\t \t \t return prefix + this.noExponents((valueSign * valueAbs).toPrecision(decimalsOnSmallNumbers)); 
 
\t \t } 
 
\t } 
 
}; 
 

 

 
CCC.TRADE = CCC.TRADE || {}; 
 
/* 
 
trade fields binary values always in the last ~ 
 
*/ 
 

 
CCC.TRADE.FLAGS = { 
 
\t 'SELL': 0x1 // hex for binary 1 
 
\t , 'BUY': 0x2 // hex for binary 10 
 
\t , 'UNKNOWN': 0x4 // hex for binary 100 
 
} 
 

 
CCC.TRADE.FIELDS = { 
 
\t 'T': 0x0 // hex for binary 0, it is a special case of fields that are always there TYPE 
 
\t , 'M': 0x0 // hex for binary 0, it is a special case of fields that are always there MARKET 
 
\t , 'FSYM': 0x0 // hex for binary 0, it is a special case of fields that are always there FROM SYMBOL 
 
\t , 'TSYM': 0x0 // hex for binary 0, it is a special case of fields that are always there TO SYMBOL 
 
\t , 'F': 0x0 // hex for binary 0, it is a special case of fields that are always there FLAGS 
 
\t , 'ID': 0x1 // hex for binary 1              ID 
 
\t , 'TS': 0x2 // hex for binary 10              TIMESTAMP 
 
\t , 'Q': 0x4 // hex for binary 100              QUANTITY 
 
\t , 'P': 0x8 // hex for binary 1000             PRICE 
 
\t , 'TOTAL': 0x10 // hex for binary 10000             TOTAL 
 

 
}; 
 

 
CCC.TRADE.DISPLAY = CCC.TRADE.DISPLAY || {}; 
 
CCC.TRADE.DISPLAY.FIELDS = { 
 
\t 'T': { "Show": false } 
 
\t , 'M': { "Show": true, 'Filter': 'Market' } 
 
\t , 'FSYM': { "Show": true, 'Filter': 'CurrencySymbol' } 
 
\t , 'TSYM': { "Show": true, 'Filter': 'CurrencySymbol' } 
 
\t , 'F': { "Show": true, 'Filter': 'TradeFlag' } 
 
\t , 'ID': { "Show": true, 'Filter': 'Text' } 
 
\t , 'TS': { 'Show': true, 'Filter': 'Date', 'Format': 'yyyy MMMM dd HH:mm:ss' } 
 
\t , 'Q': { 'Show': true, 'Filter': 'Number', 'Symbol': 'FSYM' } 
 
\t , 'P': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TSYM' } 
 
\t , 'TOTAL': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TSYM' } 
 

 
}; 
 

 
CCC.TRADE.pack = function (tradeObject) { 
 
\t var mask = 0; 
 
\t var packedTrade = ''; 
 
\t for (var field in tradeObject) { 
 
\t \t packedTrade += '~' + tradeObject[field]; 
 
\t \t mask |= this.FIELDS[field]; 
 
\t } 
 
\t return packedTrade.substr(1) + '~' + mask.toString(16); 
 
}; 
 

 
CCC.TRADE.unpack = function (tradeString) { 
 
\t var valuesArray = tradeString.split("~"); 
 
\t var valuesArrayLenght = valuesArray.length; 
 
\t var mask = valuesArray[valuesArrayLenght - 1]; 
 
\t var maskInt = parseInt(mask, 16); 
 
\t var unpackedTrade = {}; 
 
\t var currentField = 0; 
 
\t for (var property in this.FIELDS) { 
 
\t \t if (this.FIELDS[property] === 0) { 
 
\t \t \t unpackedTrade[property] = valuesArray[currentField]; 
 
\t \t \t currentField++; 
 
\t \t } 
 
\t \t else if (maskInt & this.FIELDS[property]) { 
 
\t \t \t unpackedTrade[property] = valuesArray[currentField]; 
 
\t \t \t currentField++; 
 
\t \t } 
 
\t } 
 

 
\t return unpackedTrade; 
 
} 
 

 
CCC.TRADE.getKey = function (tradeObject) { 
 
\t return tradeObject['T'] + '~' + tradeObject['M'] + '~' + tradeObject['FSYM'] + '~' + tradeObject['TSYM']; 
 
}; 
 

 
CCC.CURRENT = CCC.CURRENT || {}; 
 
/* 
 
current fields mask values always in the last ~ 
 
*/ 
 

 
CCC.CURRENT.FLAGS = { 
 
\t 'PRICEUP': 0x1 // hex for binary 1 
 
\t , 'PRICEDOWN': 0x2 // hex for binary 10 
 
\t , 'PRICEUNCHANGED': 0x4 // hex for binary 100 
 
\t , 'BIDUP': 0x8 // hex for binary 1000 
 
\t , 'BIDDOWN': 0x10 // hex for binary 10000 
 
\t , 'BIDUNCHANGED': 0x20 // hex for binary 100000 
 
\t , 'OFFERUP': 0x40 // hex for binary 1000000 
 
\t , 'OFFERDOWN': 0x80 // hex for binary 10000000 
 
\t , 'OFFERUNCHANGED': 0x100 // hex for binary 100000000 
 
\t , 'AVGUP': 0x200 // hex for binary 1000000000 
 
\t , 'AVGDOWN': 0x400 // hex for binary 10000000000 
 
\t , 'AVGUNCHANGED': 0x800 // hex for binary 100000000000 
 
}; 
 

 

 
CCC.CURRENT.FIELDS = { 
 
\t 'TYPE': 0x0  // hex for binary 0, it is a special case of fields that are always there 
 
\t , 'MARKET': 0x0  // hex for binary 0, it is a special case of fields that are always there 
 
\t , 'FROMSYMBOL': 0x0  // hex for binary 0, it is a special case of fields that are always there 
 
\t , 'TOSYMBOL': 0x0  // hex for binary 0, it is a special case of fields that are always there 
 
\t , 'FLAGS': 0x0  // hex for binary 0, it is a special case of fields that are always there 
 
\t , 'PRICE': 0x1  // hex for binary 1 
 
\t , 'BID': 0x2  // hex for binary 10 
 
\t , 'OFFER': 0x4  // hex for binary 100 
 
\t , 'LASTUPDATE': 0x8  // hex for binary 1000 
 
\t , 'AVG': 0x10  // hex for binary 10000 
 
\t , 'LASTVOLUME': 0x20  // hex for binary 100000 
 
\t , 'LASTVOLUMETO': 0x40  // hex for binary 1000000 
 
\t , 'LASTTRADEID': 0x80  // hex for binary 10000000 
 
\t , 'VOLUMEHOUR': 0x100  // hex for binary 100000000 
 
\t , 'VOLUMEHOURTO': 0x200  // hex for binary 1000000000 
 
\t , 'VOLUME24HOUR': 0x400  // hex for binary 10000000000 
 
\t , 'VOLUME24HOURTO': 0x800  // hex for binary 100000000000 
 
\t , 'OPENHOUR': 0x1000 // hex for binary 1000000000000 
 
\t , 'HIGHHOUR': 0x2000 // hex for binary 10000000000000 
 
\t , 'LOWHOUR': 0x4000 // hex for binary 100000000000000 
 
\t , 'OPEN24HOUR': 0x8000 // hex for binary 1000000000000000 
 
\t , 'HIGH24HOUR': 0x10000 // hex for binary 10000000000000000 
 
\t , 'LOW24HOUR': 0x20000 // hex for binary 100000000000000000 
 
\t , 'LASTMARKET': 0x40000 // hex for binary 1000000000000000000, this is a special case and will only appear on CCCAGG messages 
 
}; 
 

 
CCC.CURRENT.DISPLAY = CCC.CURRENT.DISPLAY || {}; 
 
CCC.CURRENT.DISPLAY.FIELDS = { 
 
\t 'TYPE': { 'Show': false } 
 
\t , 'MARKET': { 'Show': true, 'Filter': 'Market' } 
 
\t , 'FROMSYMBOL': { 'Show': false } 
 
\t , 'TOSYMBOL': { 'Show': false } 
 
\t , 'FLAGS': { 'Show': false } 
 
\t , 'PRICE': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'BID': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'OFFER': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'LASTUPDATE': { 'Show': true, 'Filter': 'Date', 'Format': 'yyyy MMMM dd HH:mm:ss' } 
 
\t , 'AVG': { 'Show': true, ' Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'LASTVOLUME': { 'Show': true, 'Filter': 'Number', 'Symbol': 'FROMSYMBOL' } 
 
\t , 'LASTVOLUMETO': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'LASTTRADEID': { 'Show': true, 'Filter': 'String' } 
 
\t , 'VOLUMEHOUR': { 'Show': true, 'Filter': 'Number', 'Symbol': 'FROMSYMBOL' } 
 
\t , 'VOLUMEHOURTO': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'VOLUME24HOUR': { 'Show': true, 'Filter': 'Number', 'Symbol': 'FROMSYMBOL' } 
 
\t , 'VOLUME24HOURTO': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'OPENHOUR': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'HIGHHOUR': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'LOWHOUR': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'OPEN24HOUR': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'HIGH24HOUR': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'LOW24HOUR': { 'Show': true, 'Filter': 'Number', 'Symbol': 'TOSYMBOL' } 
 
\t , 'LASTMARKET': { 'Show': true, 'Filter': 'String' } 
 
}; 
 

 
CCC.CURRENT.pack = function (currentObject) { 
 
\t var mask = 0; 
 
\t var packedCurrent = ''; 
 
\t for (var property in this.FIELDS) { 
 
\t \t if (currentObject.hasOwnProperty(property)) { 
 
\t \t \t packedCurrent += '~' + currentObject[property]; 
 
\t \t \t mask |= this.FIELDS[property]; 
 
\t \t } 
 
\t } 
 
\t //removing first character beacsue it is a ~ 
 
\t return packedCurrent.substr(1) + '~' + mask.toString(16); 
 
}; 
 

 
CCC.CURRENT.unpack = function (value) { 
 
\t var valuesArray = value.split("~"); 
 
\t var valuesArrayLenght = valuesArray.length; 
 
\t var mask = valuesArray[valuesArrayLenght - 1]; 
 
\t var maskInt = parseInt(mask, 16); 
 
\t var unpackedCurrent = {}; 
 
\t var currentField = 0; 
 
\t for (var property in this.FIELDS) { 
 
\t \t if (this.FIELDS[property] === 0) { 
 
\t \t \t unpackedCurrent[property] = valuesArray[currentField]; 
 
\t \t \t currentField++; 
 
\t \t } 
 
\t \t else if (maskInt & this.FIELDS[property]) { 
 
\t \t \t //i know this is a hack, for cccagg, future code please don't hate me:(, i did this to avoid 
 
\t \t \t //subscribing to trades as well in order to show the last market 
 
\t \t \t if (property === 'LASTMARKET') { 
 
\t \t \t \t unpackedCurrent[property] = valuesArray[currentField]; 
 
\t \t \t } else { 
 
\t \t \t \t unpackedCurrent[property] = parseFloat(valuesArray[currentField]); 
 
\t \t \t } 
 
\t \t \t currentField++; 
 
\t \t } 
 
\t } 
 

 
\t return unpackedCurrent; 
 
}; 
 
CCC.CURRENT.getKey = function (currentObject) { 
 
\t return currentObject['TYPE'] + '~' + currentObject['MARKET'] + '~' + currentObject['FROMSYMBOL'] + '~' + currentObject['TOSYMBOL']; 
 
}; 
 
CCC.CURRENT.getKeyFromStreamerData = function (streamerData) { 
 
\t var valuesArray = streamerData.split("~"); 
 
\t return valuesArray[0] + '~' + valuesArray[1] + '~' + valuesArray[2] + '~' + valuesArray[3]; 
 
}; 
 

 
CCC.noExponents = function (value) { 
 
\t var data = String(value).split(/[eE]/); 
 
\t if (data.length == 1) return data[0]; 
 

 
\t var z = '', sign = value < 0 ? '-' : '', 
 
\t \t str = data[0].replace('.', ''), 
 
\t \t mag = Number(data[1]) + 1; 
 

 
\t if (mag < 0) { 
 
\t \t z = sign + '0.'; 
 
\t \t while (mag++) z += '0'; 
 
\t \t return z + str.replace(/^\-/, ''); 
 
\t } 
 
\t mag -= str.length; 
 
\t while (mag--) z += '0'; 
 
\t return str + z; 
 
}; 
 

 
CCC.filterNumberFunctionPolyfill = function (value, decimals) { 
 
\t var decimalsDenominator = Math.pow(10, decimals); 
 
\t var numberWithCorrectDecimals = Math.round(value * decimalsDenominator)/decimalsDenominator; 
 
\t var parts = numberWithCorrectDecimals.toString().split("."); 
 
\t parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); 
 
\t return parts.join("."); 
 
} 
 

 
CCC.convertValueToDisplay = function (symbol, value, type, fullNumbers) { 
 
\t var prefix = ''; 
 
\t var valueSign = 1; 
 
\t value = parseFloat(value); 
 
\t var valueAbs = Math.abs(value); 
 
\t var decimalsOnBigNumbers = 2; 
 
\t var decimalsOnNormalNumbers = 2; 
 
\t var decimalsOnSmallNumbers = 4; 
 
\t if (fullNumbers === true) { 
 
\t \t decimalsOnBigNumbers = 2; 
 
\t \t decimalsOnNormalNumbers = 0; 
 
\t \t decimalsOnSmallNumbers = 4; 
 
\t } 
 
\t if (symbol != '') { 
 
\t \t prefix = symbol + ' '; 
 
\t } 
 
\t if (value < 0) { 
 
\t \t valueSign = -1; 
 
\t } 
 

 
\t if (value == 0) { 
 
\t \t return prefix + '0'; 
 
\t } 
 

 
\t if (value < 0.00001000 && value >= 0.00000100 && decimalsOnSmallNumbers > 3) { 
 
\t \t decimalsOnSmallNumbers = 3; 
 
\t } 
 
\t if (value < 0.00000100 && value >= 0.00000010 && decimalsOnSmallNumbers > 2) { 
 
\t \t decimalsOnSmallNumbers = 2; 
 
\t } 
 
\t if (value < 0.00000010 && value >= 0.00000001 && decimalsOnSmallNumbers > 1) { 
 
\t \t decimalsOnSmallNumbers = 1; 
 
\t } 
 

 
\t if (type == "short") { 
 
\t \t if (valueAbs > 10000000000) { 
 
\t \t \t valueAbs = valueAbs/1000000000; 
 
\t \t \t return prefix + CCC.filterNumberFunctionPolyfill(valueSign * valueAbs, decimalsOnBigNumbers) + ' B'; 
 
\t \t } 
 
\t \t if (valueAbs > 10000000) { 
 
\t \t \t valueAbs = valueAbs/1000000; 
 
\t \t \t return prefix + CCC.filterNumberFunctionPolyfill(valueSign * valueAbs, decimalsOnBigNumbers) + ' M'; 
 
\t \t } 
 
\t \t if (valueAbs > 10000) { 
 
\t \t \t valueAbs = valueAbs/1000; 
 
\t \t \t return prefix + CCC.filterNumberFunctionPolyfill(valueSign * valueAbs, decimalsOnBigNumbers) + ' K'; 
 
\t \t } 
 
\t \t if (valueAbs >= 1) { 
 
\t \t \t return prefix + CCC.filterNumberFunctionPolyfill(valueSign * valueAbs, decimalsOnNormalNumbers); 
 
\t \t } 
 
\t \t return prefix + (valueSign * valueAbs).toPrecision(decimalsOnSmallNumbers); 
 
\t } else { 
 
\t \t if (valueAbs >= 1) { 
 
\t \t \t return prefix + CCC.filterNumberFunctionPolyfill(valueSign * valueAbs, decimalsOnNormalNumbers); 
 
\t \t } 
 

 
\t \t return prefix + CCC.noExponents((valueSign * valueAbs).toPrecision(decimalsOnSmallNumbers)); 
 
\t } 
 
};

0

La bibliothèque socketIO_client ne semble pas soutenir le protocole d'interrogation XHR qui est utilisé par cryptocompare. Je l'ai eu pour travailler en remplaçant la méthode recv_packet dans la classe socketIO_client.transports.XHR_PollingTransport.

import logging 
import socketIO_client 
from socketIO_client.transports import get_response 
from socketIO_client.parsers import get_byte, _read_packet_text, parse_packet_text 

from requests.exceptions import ConnectionError 

# extra function to support XHR1 style protocol 
def _new_read_packet_length(content, content_index): 
    packet_length_string = '' 
    while get_byte(content, content_index) != ord(':'): 
     byte = get_byte(content, content_index) 
     packet_length_string += chr(byte) 
     content_index += 1 
    content_index += 1 
    return content_index, int(packet_length_string) 

def new_decode_engineIO_content(content): 
    content_index = 0 
    content_length = len(content) 
    while content_index < content_length: 
     try: 
      content_index, packet_length = _new_read_packet_length(
       content, content_index) 
     except IndexError: 
      break 
     content_index, packet_text = _read_packet_text(
      content, content_index, packet_length) 
     engineIO_packet_type, engineIO_packet_data = parse_packet_text(
      packet_text) 
     yield engineIO_packet_type, engineIO_packet_data 

def new_recv_packet(self): 
    params = dict(self._params) 
    params['t'] = self._get_timestamp() 
    response = get_response(
     self.http_session.get, 
     self._http_url, 
     params=params, 
     **self._kw_get) 
    for engineIO_packet in new_decode_engineIO_content(response.content): 
     engineIO_packet_type, engineIO_packet_data = engineIO_packet 
     yield engineIO_packet_type, engineIO_packet_data 

setattr(socketIO_client.transports.XHR_PollingTransport, 'recv_packet', new_recv_packet) 

logging.basicConfig(level=logging.DEBUG) 

try: 
    socket = socketIO_client.SocketIO('https://streamer.cryptocompare.com') 
    socket.emit('SubAdd', { 'subs': ['0~Kraken~BTC~USD'] }); 
    socket.wait() 
except ConnectionError: 
    print('The server is down. Try again later.') 

La solution est fortement basée sur ce commentaire github: https://github.com/invisibleroads/socketIO-client/issues/129#issuecomment-330058318