【Python】pubnub を使って bitflyer の Ticker 情報をリアルタイム表示する
おはようございます。
今回は、pubnubというサービスを用いてリアルタイムメッセージング機能というのを試してみたくて色々調べてみました。
(ただ、結果的にあまりうまくできてませんが)
pubnubについて調べていると Bitflyer(仮想通貨取引所)が板等の更新情報を配信しているということなので、それを利用してWEBサービスにリアルタイムでデータを表示してみます。
スポンサーリンク
新規プロジェクトの作成
PyCharmを起動し、新しくプロジェクトを作成します。
今回は「BfTool」としました。
プロジェクトの作成については、大した手順ではないですが次の記事を参考にしてください。
【Python】PyCharmのインストールからHello Worldまで
また、構成は次の通りです。
BfTool
│ Sample.py
├─static
│ ├─css
│ │ style.css
│ └─js
│ script.js
├─templates
│ index.html
└─venv
パッケージ追加
今回は Tornado の他に「pubnub」というパッケージを追加します。
パッケージ追加の方法についても前回の記事を参考にしていただけると幸いです。
【Python】PyCharm でパッケージ追加と別ファイルのクラス読込
画面の作成
index.html
<!DOCTYPE html> <html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ static_url('css/style.css') }}"/> <script type="text/javascript" src="{{ static_url('js/script.js') }}"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> </head> <body> <div id="container"> <div style="clear:both; padding-top:10px;"> <table id="dataTable"> <tr id="header"> <th style="width:5%">種別</th> <th style="width:10%">時刻</th> <th style="width:5%">ID</th> <th style="width:5%">売値</th> <th style="width:5%">買値</th> <th style="width:10%">売り数量</th> <th style="width:10%">買い数量</th> <th style="width:10%">売り注文総数</th> <th style="width:10%">買い注文総数</th> <th style="width:10%">最終取引価格</th> <th style="width:10%">出来高</th> <th style="width:10%">価格単位出来高</th> </tr> </table> </div> </div> </body> </html>
style.css
body { font-family:"MS Pゴシック","MS PGothic",sans-serif; width: 100%; margin: 0 auto; } div { margin:20px; } div#container{ width: 100%; } table { width:95%; border: 1px solid #ccc; border-collapse:collapse; } th { text-align:center; background-color:#404040; color:#ffffff; width: 100px; height: 25px; border: 1px solid #ccc; } td { padding-left:5px; width: 200px; height: 20px; border: 1px solid #ccc; }
プログラムの作成
Sample.py
import json import logging import os import signal import time import tornado.ioloop import tornado.web import tornado.websocket from tornado.options import options from pubnub.pnconfiguration import PNConfiguration from pubnub.pubnub import PubNub, SubscribeListener is_closing = False pb = None my_listener = None def signal_handler(signum, stack): u""" サーバー停止信号を受信した際にフラグをオンにします.""" global is_closing logging.info("exiting...") is_closing = True def try_exit(): u""" サーバー停止フラグがオンの場合にインスタンスを停止します. """ global is_closing if is_closing: # clean up here tornado.ioloop.IOLoop.instance().stop() logging.info("exit success") class MainHandler(tornado.web.RequestHandler): u""" メイン処理 """ def initialize(self): logging.info("initialize") def get(self): self.render("index.html", title="Pythonサンプル") class SendWebSocket(tornado.websocket.WebSocketHandler): def open(self): logging.info('SendWebSocket IP:' + self.request.remote_ip) self.ioloop = tornado.ioloop.IOLoop.instance() self.send_websocket() def on_close(self): print("Session closed") global pb global my_listener pb.unsubscribe().channels(['lightning_ticker_BTC_JPY', 'lightning_ticker_FX_BTC_JPY']).execute() my_listener.wait_for_disconnect() def check_origin(self, origin): return True def send_websocket(self): self.ioloop.add_timeout(time.time() + 1, self.send_websocket) if self.ws_connection: global pb global my_listener # Bitflyer の キーを設定してインスタンスを生成、 # リスナーを追加 pnc = PNConfiguration() pnc.subscribe_key = "sub-c-52a9ab50-291b-11e5-baaa-0619f8945a4f" pnc.ssl = False pb = PubNub(pnc) my_listener = SubscribeListener() pb.add_listener(my_listener) # チャンネルの設定 pb.subscribe().channels(['lightning_ticker_BTC_JPY', 'lightning_ticker_FX_BTC_JPY']).execute() my_listener.wait_for_connect() # BTC-FX/JPY の結果を取得 fx_result = my_listener.wait_for_message_on('lightning_ticker_FX_BTC_JPY') fx_data = fx_result.message message = json.dumps(fx_data) logging.info(message) self.write_message(message) app = tornado.web.Application([ (r"/", MainHandler), (r"/ticker", SendWebSocket) ], template_path=os.path.join(os.getcwd(), "templates"), static_path=os.path.join(os.getcwd(), "static"), js_path=os.path.join(os.getcwd(), "js"), ) if __name__ == "__main__": tornado.options.parse_command_line() signal.signal(signal.SIGINT, signal_handler) app.listen(8888) logging.info("server started") tornado.ioloop.PeriodicCallback(try_exit, 100).start() tornado.ioloop.IOLoop.instance().start()
script.js
// スクリプト読み込み時の処理 function initialize() { var connection = new WebSocket('ws://127.0.0.1:8888/ticker'); connection.onmessage = function (e) { var data = JSON.parse(e.data.replace( /\\/g , "" )); var table = $("#dataTable"); // 日付け変換 var date = new Date(data.timestamp); data.timestamp = date.toLocaleString(); // テーブルに追加 var tr = document.createElement("tr"); $.each(data, function(i, cell){ var td = document.createElement("td"); td.innerHTML = cell; tr.appendChild(td); }); $(tr).insertAfter("#header"); }; }
起動してみる
起動後、「http://localhost:8888」にアクセスします。
1秒間隔で情報が更新され、テーブルにデータが追加されていきます。
まとめ
本当は Bitflyer からの更新情報のメッセージを受信(をトリガーに)してデータ表示を更新させるようにしたかったのですが、Tornado の WEBサーバーと同時に起動する方法で嵌ったので仕方なくこういった形になりました。
別スレッドや別プロセスで動かせばいいのかなとか考えたのですが、まあとりあえず表示したかったので。。
次回以降もうちょっと調べてみようと思います。
ではでは。
ディスカッション
コメント一覧
まだ、コメントがありません