Полная разработка стека - выборка данных, визуализация с помощью D3 и развертывание с помощью Dokku

Полная разработка стека - выборка данных, визуализация с помощью D3 и развертывание с помощью Dokku

В этом руководстве мы создадим веб-приложение, которое будет собирать данные изNASDAQ-100 и визуализировать их в виде пузырьковой диаграммы с помощью D3. Затем, в довершение всего, мы развернем это в Digital Ocean через Dokku.

Note: Пузырьковые диаграммы идеально подходят для визуализации сотен значений на небольшом пространстве. Тем не менее, их труднее читать, потому что может быть трудно различить круги одинакового размера. Если вы работаете только с несколькими значениями, гистограмма, вероятно, является лучшим вариантом, поскольку ее гораздо легче читать.

Основные инструменты, используемые в этом руководстве: Python v2.7.8, Flask v0.10.1,Requests v2.4.1, D3 v3.4.11, Dokku v0.2.3 и Bower v1.3.9.

Начните с поиска и загрузки файла_app_boilerplate.zip из этогоrepo. Этот файл содержит шаблон Flask. После загрузки извлеките файл и папки, активируйте virtualenv иinstall the dependencies with Pip:

pip install -r requirements.txt

Затем проверьте, работает ли он: запустите сервер, откройте браузер и перейдите кhttp://localhost:5000/. Вы должны увидеть «Привет, мир!» уставившись на тебя.

Получение данных

Создайте новый маршрут и функцию просмотра в файле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 в основной каталог.

Your turn: Создайте сценарий самостоятельно, выполнив следующие действия:

  1. Загрузите CSV изhttp://www.nasdaq.com/quotes/nasdaq-100-stocks.aspx?render=download.

  2. Соберите соответствующие данные из CSV: название акции, символ акции, текущая цена, чистое изменение, процентное изменение, объем и стоимость.

  3. Преобразуйте проанализированные данные в словарь Python.

  4. Верните словарь.

Как прошло? Нужна помощь? Давайте посмотрим на одно из возможных решений:

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

Что происходит?

  1. Здесь мы получаем URL-адрес с помощью запроса GET, а затем конвертируем объект Response,r, вunicode.

  2. Затем мы работаем с библиотекойCSV, чтобы преобразовать текст, разделенный запятыми, в экземпляр классаDictReader(), который отображает данные в словарь, а не в список.

  3. Наконец, после перебора данных и создания списка словарей (где каждый словарь представляет разные акции) мы возвращаем dictRESULTS.

Note
Вы также можете использовать понимание диктовки для создания отдельных словарей. Это гораздо более эффективный метод, однако вы жертвуете удобочитаемостью. Ваш звонок.

Time to test: запустите сервер, а затем перейдите кhttp://localhost:5000/data. Если все прошло хорошо, вы должны увидеть объект, содержащий соответствующие данные о запасах.

Имея данные под рукой, мы можем теперь работать с их визуализацией во внешнем интерфейсе.

Визуальное

Наряду с HTML и CSS мы будем использоватьBootstrap, Javascript / jQuery иD3 для поддержки нашего интерфейса. Мы также будем использовать клиентский инструмент управления зависимостямиBower для загрузки этих библиотек и управления ими.

Your turn: Следуйтеinstallation instructions, чтобы настроить Bower на вашем компьютере. Hint: You will need to install Node.js before you install Bower.

Готовы?

Беседка

Для запуска беседки необходимы два файла -bower.json и.http://bower.io/docs/config/[bowerrc].

Последний файл используется для настройки Bower. Добавьте его в основной каталог:

{
  "directory": "static/bower_components"
}

Это просто указывает на то, что мы хотим, чтобы зависимости были установлены в каталогеbower_components (соглашение) внутри каталога приложенияstatic.

Между тем, первый файл,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



  
    Flask Stock Visualizer
    
    
    
  
  
    

D3

Почему существует так много фреймворков визуализации данных, почемуD3? Ну, D3 - это довольно низкий уровень, поэтому он позволяет вам создавать тот тип фреймворка, который вы хотите. Когда вы добавляете свои данные в DOM, вы используете комбинацию CSS3, HTML5 и SVG для создания фактической визуализации. Затем вы можете добавить интерактивности через встроенный в D3transitions, управляемый данными.

Если честно, эта библиотека не для всех. Поскольку у вас есть большая свобода строить то, что вы хотите, кривая обучения довольно высока. Если вам нужен быстрый старт, посмотритеPython-NVD3, оболочку для D3, которая значительно упрощает работу с D3. Мы не используем его для этого урока, так как Python-NVD3 не поддерживает пузырьковые диаграммы.

Your turn: пройти D3intro 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 работает!», Если все прошло хорошо.

Добавьте следующий тег в файлindex.html внутри тега<div>, который имеетid изcontainer (после строки 10), чтобы удерживать пузырьковую диаграмму D3:

Главный Конфиг

Добавьте следующий код в функциюcreateGraph() вmain.js:

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

Обязательно ознакомьтесь с комментариями к коду для объяснения, а также с официальным D3documentation. Посмотри что-нибудь, чего ты не понимаешь. A coder must be self-reliant!

Bubble Config

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() и проверьтеdocs на наличие вопросов.

SVG Config

Затем добавьте следующий код вcreateGraph(), который выбирает элемент сid изchart, а затем добавляет кружки вместе с рядом атрибутов:

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. Это стандартный шаблон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/. Теперь, когда вы наведите курсор на кружок, вы увидите некоторые основные метаданные - название компании и цену акций.

Your turn: добавить больше метаданных. Какие еще данные вы считаете актуальными? Подумайте о том, что мы показываем здесь - относительное изменение цены. Возможно, вы могли бы рассчитать предыдущую цену и показать:

  1. Текущая цена

  2. Относительное изменение

  3. Предыдущая цена

Refactor

акции Что, если бы мы просто хотели визуализировать акции с модифицированным индексом, взвешенным по рыночной стоимости - NASDAQ-100 Pointscolumn - больше, чем .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.

Мы используемDigital Ocean в качестве хоста. Давайте начнем.

Настройка Digital Ocean

Sign up для учетной записи, если у вас ее еще нет. Затем следуйте этомуguide, чтобы добавить открытый ключ.

Создайте новую каплю - укажите имя, размер и местоположение. Для изображения нажмите вкладку «Приложения» и выберите приложение Dokku. Обязательно выберите свой SSH-ключ.

После создания завершите настройку, введя IP-адрес недавно созданной капли в браузере, после чего откроется экран настройки Dokku. Убедитесь, что открытый ключ верен, затем нажмите «Завершить настройку».

Теперь VPS может принимать толчки.

Развернуть Config

  1. Создайте Procfile со следующим кодом:web: gunicorn app:app. (Этот файл содержит команду, которая должна быть запущена для запуска веб-процесса.)

  2. Установите gunicorn:pip install gunicorn

  3. Обновите файлrequirements.txt:pip freeze > requirements.txt

  4. Инициализировать новый локальный репозиторий Git:git init

  5. Добавьте пульт:git remote add dokku [email protected]: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-адрес вместе с правильным портом.) Вы должны увидеть свое живое приложение! (Смотрите изображение в верхней части этого поста для предварительного просмотра.)

Следующие шаги

Хотите поднять это на следующий уровень? Добавьте в приложение следующие функции:

  1. Обработка ошибок

  2. Модульное тестирование

  3. Интеграционное тестирование

  4. Непрерывная интеграция / доставка

Эти функции (и многое другое!) Будут включены в следующий выпуск курсовReal Python, который выйдет в начале октября 2014 года!

Комментарий ниже, если у вас есть вопросы.

Ура!

Related