フルスタック開発–データの取得、D3による視覚化、およびDokkuによる展開
このチュートリアルでは、http://www.nasdaq.com/quotes/nasdaq-100-stocks.aspx [NASDAQ-100]からデータを取得するためのWebアプリケーションを構築し、D3でバブルグラフとして視覚化します。 それから締めくくりに、これをDokku経由でDigital Oceanに展開します。
_ *注:*バブルチャートは、小さなスペースで数百の値を視覚化するのに最適です。 ただし、同じサイズの円を区別することは難しいため、読みにくくなっています。 いくつかの値のみを使用している場合、棒グラフは読みやすいため、おそらくより良いオプションです。 _
このチュートリアルで使用されるメインツール:Python v2.7.8、Flask v0.10.1、https://realpython.com/python-requests/[Requests] v2.4.1、D3 v3.4.11、Dokku v0.2.3、およびBower v1。 3.9
このhttps://github.com/realpython/flask-stock-visualizer[repo]から__app_boilerplate.zip_ファイルを見つけてダウンロードすることから始めます。 このファイルには、Flaskボイラープレートが含まれています。 ダウンロードしたら、ファイルとフォルダーを抽出し、virtualenvをアクティブにして、https://realpython.com/what-is-pip/[Pipで依存関係をインストール]:
pip install -r requirements.txt
次に、テストして機能することを確認します。サーバーを起動し、ブラウザーを開いて、http://localhost:5000/に移動します。 「Hello、world!」と表示されるはずです。あなたを見つめなおします。
データの取得
_app.py_ファイルに新しいルートとビュー関数を作成します。
@app.route("/data")
def data():
return jsonify(get_data())
インポートを更新します。
from flask import Flask, render_template, jsonify
from stock_scraper import get_data
そのため、そのルートが呼び出されると、 `+ get_data()+`という関数から返された値をJSONに変換して返します。 この関数は_stock_scraper.py_というファイルにありますが、これは驚きです! -NASDAQ-100からデータを取得します。
スクリプト
_stock_scraper.py_をメインディレクトリに追加します。
あなたの番:次の手順に従って、自分でスクリプトを作成します。
-
http://www.nasdaq.com/quotes/nasdaq-100-stocks.aspx?render=downloadからCSVをダウンロードします。
-
CSVから関連データを取得します:銘柄名、銘柄記号、現在の価格、正味の変化、パーセントの変化、ボリューム、および値。
-
解析されたデータをPython辞書に変換します。
-
辞書を返します。
どうだった? 助けが必要? 考えられる解決策を1つ見てみましょう。
import csv
import requests
URL = "http://www.nasdaq.com/quotes/nasdaq-100-stocks.aspx?render=download"
def get_data():
r = requests.get(URL)
data = r.text
RESULTS = {'children': []}
for line in csv.DictReader(data.splitlines(), skipinitialspace=True):
RESULTS['children'].append({
'name': line['Name'],
'symbol': line['Symbol'],
'symbol': line['Symbol'],
'price': line['lastsale'],
'net_change': line['netchange'],
'percent_change': line['pctchange'],
'volume': line['share_volume'],
'value': line['Nasdaq100_points']
})
return RESULTS
何が起こっていますか?
-
ここでは、GETリクエストを介してURLをフェッチし、Responseオブジェクト `+ r +`をhttps://realpython.com/python-encodings-guide/[unicode]に変換します。
-
次に、 `+ CSV `ライブラリを操作して、コンマ区切りのテキストを ` DictReader()+`クラスのインスタンスに変換します。このクラスは、データをリストではなく辞書にマップします。
-
最後に、データをループし、辞書のリストを作成した後(各辞書は異なるストックを表します)、 `+ RESULTS +`の辞書を返します。
_ NOTE You could also use a dict comprehension to create the individual dictionaries. This is a much more efficient method, however you sacrifice readability. Your call. _
テストする時間:サーバーを起動し、http://localhost:5000/dataに移動します。 すべてうまくいけば、関連する株式データを含むオブジェクトが表示されます。
データが手元にあれば、フロントエンドで視覚化することができます。
視覚化
HTMLとCSSとともに、http://getbootstrap.com/[Bootstrap]、Javascript/jQuery、およびhttp://d3js.org/[D3]を使用してフロントエンドを強化します。 また、クライアント側の依存関係管理ツールhttp://bower.io/[Bower]を使用して、これらのライブラリをダウンロードおよび管理します。
あなたの番:https://github.com/bower/bower#install [インストール手順]に従って、マシンにBowerをセットアップします。 _ヒント:Bower_をインストールする前に、http://nodejs.org/download/[Node.js]をインストールする必要があります。
準備はいい?
バウアー
bowerを使用するには2つのファイルが必要です-http://bower.io/docs/creating-packages/#bowerjson [bower.json] _および.http://bower.io/docs/config/[bowerrc] _ 。
後者のファイルは、Bowerの構成に使用されます。 メインディレクトリに追加します。
{
"directory": "static/bower_components"
}
これは、アプリの_static_ディレクトリ内の_bower_components_ディレクトリ(慣習)に依存関係をインストールすることを指定するだけです。
一方、最初のファイル_bower.json_はBowerマニフェストを格納します。つまり、このファイルにはBowerコンポーネントとアプリケーション自体に関するメタデータが含まれています。 ファイルは、 `+ bower init +`コマンドを使用してインタラクティブに作成できます。 今それをしてください。 すべてのデフォルトをそのまま使用します。
これで、依存関係をインストールできます。
$ bower install bootstrap#3.2.0 jquery#2.1.1 d3#3.4.11 --save
+-save +`フラグは、パッケージを_bower.json_依存関係配列に追加します。 見てみな。 また、_bower.json_の依存関係バージョンが、指定したバージョン(つまり、 `+ bootstrap#3.20 +
)に一致することを確認してください。
依存関係をインストールしたら、アプリでアクセスできるようにします。
_index.html_を更新
<!DOCTYPE html>
<html>
<head>
<title>Flask Stock Visualizer</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href={{ url_for('static', filename='./bower_components/bootstrap/dist/css/bootstrap.min.css') }} rel="stylesheet" media="screen">
<link href={{ url_for('static', filename='main.css') }} rel="stylesheet" media="screen">
</head>
<body>
<div class="container">
</div>
<script src={{ url_for('static', filename='./bower_components/jquery/dist/jquery.min.js') }}></script>
<script src={{ url_for('static', filename='./bower_components/bootstrap/dist/js/bootstrap.min.js') }}></script>
<script src={{ url_for('static', filename='./bower_components/d3/d3.min.js') }}></script>
<script src={{ url_for('static', filename='main.js') }}></script>
</body>
</html>
D3
非常に多くのデータ視覚化フレームワークがあるのに、なぜhttp://d3js.org/[D3]なのですか? D3はかなり低レベルなので、必要な種類のフレームワークを構築できます。 データをDOMに追加したら、CSS3、HTML5、およびSVGのコンボを使用して、実際の視覚化を作成します。 次に、D3の組み込みのデータ駆動型https://github.com/mbostock/d3/wiki/Transitions[transitions]を介してインタラクティブ機能を追加できます。
公平を期すため、このライブラリは万人向けではありません。 必要なものを自由に作成できるため、学習曲線はかなり高くなります。 クイックスタートをお探しの場合は、https://github.com/areski/python-nvd3 [Python-NVD3]をご覧ください。これはD3のラッパーであり、D3の操作をはるかに簡単にするために使用されます。 Python-NVD3はバブルチャートをサポートしていないため、このチュートリアルでは使用していません。
あなたの番:D3 intro tutorialをご覧ください。
それでは、コーディングしましょう。
セットアップ
_main.js_に次のコードを追加します。
//Custom JavaScript
$(function() {
console.log('jquery is working!');
createGraph();
});
function createGraph() {
//Code goes here
}
ここでは、最初のページの読み込み後、「jquery is working!」をコンソールに記録し、「+ createGraph()+」という関数を起動します。 これをテストしてください。 サーバーを起動し、http://localhost:5000/に移動し、JavaScriptコンソールを開いてページを更新します。 すべてがうまくいけば、「jquery is working!」というテキストが表示されます。
次のタグを_index.html_ファイルに追加します。これは、D3バブルチャートを保持するために、 `+ container `の ` id `を持つ ` <div> +`タグ内(10行目以降)に追加します。
<div id="chart"></div>
メイン設定
_main.js_の `+ createGraph()+`関数に次のコードを追加します。
var width = 960;//chart width
var height = 700;//chart height
var format = d3.format(",d"); //convert value to integer
var color = d3.scale.category20(); //create ordinal scale with 20 colors
var sizeOfRadius = d3.scale.pow().domain([-100,100]).range([-50,50]); //https://github.com/mbostock/d3/wiki/Quantitative-Scales#pow
外植のコードコメントと、公式のD3 documentationを参照してください。 わからないことは何でも調べてください。 コーダーは自立していなければなりません!
バブル構成
var bubble = d3.layout.pack()
.sort(null) //disable sorting, use DOM tree traversal
.size([width, height]) //chart layout size
.padding(1) //padding between circles
.radius(function(d) { return 20 + (sizeOfRadius(d) * 30); }); //radius for each circle
再度、上記のコードを `+ createGraph()+`関数に追加し、https://github.com/mbostock/d3/wiki/Pack-Layout [docs]で質問を確認します。
SVG構成
次に、次のコードを `+ createGraph()`に追加します。このコードは、 ` chart `の ` id +`を持つ要素を選択し、いくつかの属性とともに円を追加します。
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "bubble");
`+ createGraph()+`関数を続けて、D3と非同期で実行できるデータを取得する必要があります。
データをリクエストする
//REQUEST THE DATA
d3.json("/data", function(error, quotes) {
var node = svg.selectAll('.node')
.data(bubble.nodes(quotes)
.filter(function(d) { return !d.children; }))
.enter().append('g')
.attr('class', 'node')
.attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'});
node.append('circle')
.attr('r', function(d) { return d.r; })
.style('fill', function(d) { return color(d.symbol); });
node.append('text')
.attr("dy", ".3em")
.style('text-anchor', 'middle')
.text(function(d) { return d.symbol; });
});
そのため、データを返すために以前に設定した「+/data +」エンドポイントをヒットします。 このコードの残りは、バブルとテキストをDOMに追加するだけです。 これは標準ボイラープレートhttp://bl.ocks.org/mbostock/4063269[code]であり、データ用にわずかに変更されています。
ツールチップ
`+ createGraph()+`関数内にあるグラフのスペースは限られているため、特定の株式に関する追加情報を表示するツールチップを追加しましょう。
//tooltip config
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("color", "white")
.style("padding", "8px")
.style("background-color", "rgba(0, 0, 0, 0.75)")
.style("border-radius", "6px")
.style("font", "12px sans-serif")
.text("tooltip");
これらは、ツールチップに関連付けられているCSSスタイルです。 実際のデータを追加する必要があります。 DOMに円を追加するコードを更新します。
node.append("circle")
.attr("r", function(d) { return d.r; })
.style('fill', function(d) { return color(d.symbol); })
.on("mouseover", function(d) {
tooltip.text(d.name + ": $" + d.price);
tooltip.style("visibility", "visible");
})
.on("mousemove", function() {
return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");
})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");});
これをテストし、http://localhost:5000/に移動します。 円にカーソルを合わせると、基になるメタデータ(会社名と株価)が表示されます。
あなたの番:メタデータを追加します。 関連する他のデータは何ですか? ここで表示しているもの、つまり価格の相対的な変化を考えてください。 おそらく前の価格を計算して表示できます:
-
現在の価格
-
相対的な変化
-
以前の価格
リファクタリング
株式修正された市場価値加重インデックスで株式を視覚化したい場合はどうでしょうか-NASDAQ-100ポイントhttp://www.nasdaq.com/quotes/nasdaq-100-stocks.aspx[column]-.1より大きい?
`+ get_data()+`関数に条件を追加します:
def get_data():
r = requests.get(URL)
data = r.text
RESULTS = {'children': []}
for line in csv.DictReader(data.splitlines(), skipinitialspace=True):
if float(line['Nasdaq100_points']) > .01:
RESULTS['children'].append({
'name': line['Name'],
'symbol': line['Symbol'],
'symbol': line['Symbol'],
'price': line['lastsale'],
'net_change': line['netchange'],
'percent_change': line['pctchange'],
'volume': line['share_volume'],
'value': line['Nasdaq100_points']
})
return RESULTS
_main.js_のバブル設定セクションで、各バブルの半径を増やしましょう。それに応じてコードを変更します。
//Radius for each circle
.radius(function(d) { return 20 + (sizeOfRadius(d) * 60); });
CSS
最後に、_main.css_にいくつかの基本的なスタイルを追加しましょう。
body {
padding-top: 20px;
font: 12px sans-serif;
font-weight: bold;
}
見栄えは? 展開する準備はできましたか?
展開する
Dokkuは、オープンソースのHerokuライクなPlatform as a Service(PaaS)であり、Dockerを使用しています。 セットアップしたら、Gitでアプリをプッシュできます。
ホストとしてhttps://www.digitalocean.com/[Digital Ocean]を使用しています。 始めましょう。
デジタルオーシャンのセットアップ
アカウントをまだお持ちでない場合は、https://cloud.digitalocean.com/registrations/new [サインアップ]してください。 次に、このhttps://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys—2 [ガイド]に従って公開鍵を追加します。
新しいドロップレットを作成-名前、サイズ、場所を指定します。 画像については、「アプリケーション」タブをクリックして、Dokkuアプリケーションを選択します。 必ずSSHキーを選択してください。
作成したら、新しく作成したドロップレットのIPをブラウザに入力してセットアップを完了します。これにより、Dokkuのセットアップ画面が表示されます。 公開鍵が正しいことを確認して、「セットアップの完了」をクリックします。
これで、VPSはプッシュを受け入れることができます。
構成の展開
-
次のコードでProcfileを作成します:
+ web:gunicorn app:app +
。 (このファイルには、Webプロセスを開始するために実行する必要があるコマンドが含まれています。) -
gunicornのインストール:
+ pip install gunicorn +
-
_requirements.txt_ファイルを更新します:
+ pip freeze> requirements.txt +
-
新しいローカルGitリポジトリを初期化する:
+ git init +
-
リモートを追加します:
+ git remote add dokku dokku@192.241.208.61:app_name +
(必ず独自のIPアドレスを追加してください。)
_app.py_の更新:
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port)
そのため、最初にアプリの環境からポートを取得しようとします。見つからない場合は、デフォルトでポート5000に設定されます。
インポートも必ず更新してください:
import os
デプロイ!
変更をコミットしてからプッシュします: + git push dokku master +
。 すべてうまくいけば、端末にアプリケーションのURLが表示されるはずです。
=====> Application deployed:
http://192.241.208.61:49155
それをテストします。 http://192.241.208.61:49155に移動します。 (繰り返しますが、正しいポートとともに独自のIPアドレスを追加してください。)ライブアプリが表示されるはずです。 (プレビューについては、この投稿の上部にある画像を参照してください。)
次のステップ
これを次のレベルに上げたいですか? 次の機能をアプリに追加します。
-
エラー処理
-
単体テスト
-
統合テスト
-
継続的な統合/配信
_ これらの機能(およびその他!)は、2014年10月上旬に提供されるhttps://realpython.com [Real Python]コースの次のエディションに含まれます! _
質問がある場合は、以下にコメントしてください。
乾杯!