Архивист — ламповый консольный API-архиватор

от автора

Две причины побудили меня написать эту статью и небольшой MVP.

  1. Потребность в большем объеме сырых данных с наших рынков. Большую часть из них я могу получать посредством API. Такую возможность предоставляет и Московская биржа, и Т-Банк и Финам. Причем, речь идет не о разовой загрузке больших архивов, а скорей о регулярных задачах, которые должны выполняться с определенной периодичностью.

  2. Ностальгия по ламповому TUI(Text User Interface). В этом направлении всегда было место для творчества в условиях ограничений в части отображения (картинки и графики особо не покажешь). Но есть и преимущество — консольное приложение в сравнении с GUI — не столь требовательно к ресурсам и по сути может работать везде, где есть текстовая консоль, ну а в случае моего MVP — еще и Python.

В статье описал личную историю вдохновления, ссылку на код проекта ну и небольшую инструкцию.

Все началось с того, что я случайно, открыл для себя фреймворк Textual (здесь можно посмотреть и документацию и примеры работ). Особенно вдохновил интерфейс Dolphie, вот он

Не знаю как вам, а мне очень понравилось. Что еще мне понравилось в Textual:

  • набор готовых виджетов, начиная от кнопок из списков, заканчивая datatable. И да, “Это Питон, детка!” — можно создавать свои виджеты, наследуя и дорабатывая имеющиеся

  • палитра команд и хоткеи

  • событийность и обмен сообщениями между компонентами

  • асинхронность под капотом. Ну к примеру посредством set_interval можно задавать периодичность фонового запуска какой-либо функции

  • CSS… да 🙂 О дивный новый мир 🙂 Сильно упрощенный, но удобно в части настройки компоновки визуальных элементов

  • реактивность. Ага прям как в js-фреймворках, но разработчики честно признаются, что лучше избегать этого механизма

  • “тематизация” — возможность выбора цветовой палитры на свой вкус

  • всплывающие сообщения (Notify), причем разной степени важности (Info/Warning/Critical)

  • и как вишенка на торте — вы можете использовать textual-serve. Это модуль поднимает небольшой веб-сервер и посредством xterm.js отображает ваше приложение в браузере. Выглядит также как и в консоли, наверняка удобно использовать, но не уверен в части безопасности

Использование

Ссылка на код проекта и инструкции по установке на github

Для демонстрации буду использовать собранный под Windows дистрибутив. Для этого заходим в папку dist и скачиваем архив archivist_0.0.1.zip Распаковываем, запускаем единственный файл archivist.exe.

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

Вот такой упрощенный внешний вид, с парочкой примеров задач.

Что мы здесь видим:

  • две задачки по загрузке итогов торгов акциями IBM

  • третья строка, с именем Example — шаблон задачи, который мы будем править

Но, первым делом надо зайти в настройки (нажав F3) и поменять значение параметра data_folder. По умолчанию стоит “.”, что говорит о том, что данные выгружаются в папку data в текущей папке проекта. Однако здесь есть ньюанс для собранных под Windows приложений Python — по сути это архивы, которые сначала распаковываются во временную папку и оттуда уже запускаются. Соответственно и папка data оказывается там же, что неудобно. Поэтому указываем свой путь для хранения данных, например как показано на рисунке

Обратите внимание, что значение указано в кавычках, и используется знак «\\» как разделитель. Это все особенности описания настроек в формате json. Далее нажимаем “Ctrl+s” для сохранения настроек. Автоматически произойдет переход на основной экран.

Обе задачки заведены для выполнения с интервалом каждые пять минут, но если мы хотим протестировать настройки, достаточно выбрать одну из задач и нажать F9. После нажатия произойдет выгрузка в файл в указанную в настройках папку. На данном примере — в папке data появиться папка IBM, внутри которой будет файл с указанным расширением (csv/json) и именем равным текущей дате.

Загрузка данных с Мосбиржи.

Давайте попробуем более интересную задачку. Вот ссылка на страницу итогов торгов по инструментам(да в браузере также открывается): https://iss.moex.com/iss/engines/stock/markets/shares/securities.json

Да, сервис московской биржи великолепен и мы можем забирать данные сразу в формате csv/json/html, но в контексте данного примера — попробуем забирать и главное разбирать именно json.

Вот так примерно выглядят данные

Давайте попробуем настроить новую задачку, которая будет забирать эти данные, и укладывать их в файл. Причем, что важно, мне не нужна секция metadata файла (шапка), я хочу складывать в файл, сразу содержимое секции securities/data. И чтобы все было сразу в формате csv.

На главном экране нажимаем F2 и переходим в режим редактирования задач. Мы можем поправить или существующую шаблонную задачку с именем Example, или добавить новую в текущий файл конфигурации. Добавляем следующий конфиг:

 {      "name": "moex_securities",      "request_method": "GET",      "request_url": "https://iss.moex.com/iss/engines/stock/markets/shares/securities.json",      "request_headers": "",      "request_body": "{}",      "comment": "shares -> securities",      "interval": "5min",      "file_save_mode": "rewrite",      "file_format": "csv",      "json_key": "securities/data"}

Не забываем про запятые между фигурными скобками. В итоге должно получиться примерно вот так:

Что важно здесь отметить:

  • file_save_mode: если хотит перезаписывать файл при очередном заборе данных — ставим режим rewrite, если дозаписывать — append

  • json_key: если мы забираем данные в формате json и нас интересует лишь значения конкретного ключа, тогда указываем их через слэш. В данном примере “securities/data”. Если хотим забирать вообще все — указываем пустую строку “”

  • file_format: указали вывод в csv (можем указать csv или json или html). И да, у меня конвертирование данных в формат csv сделан очень по деревянному (заменой символов), возможно исправлю со временем, но пока — как есть.

  • interval: 5min/10min/30min/60min/1day

Нажимаем “ctrl+s” для сохранения. Если вы все сделали правильно, то на главном экране появляется новая строка. Выбираем ее и тестируем получение данных, нажав F9. Заходим в нашу папку data, смотрим содержимое полученного файла.

Загрузка данных с Т-Банк

Здесь чуть сложнее. Данные забираются посредством POST-запросов, причем в хэдере (headers) должен быть указан ваш токен, который насколько я помню живет порядка 3 месяцев с момента генерации. Но порядок тот же.

Снова нажимаем F2, и вносим следующие настройки в конфигурацию:

{        "name": "tb_last_prices",        "request_method": "POST",        "request_url": "https://invest-public-api.tinkoff.ru/rest/tinkoff.public.invest.api.contract.v1.MarketDataService/GetLastPrices",        "request_headers": {            "Authorization": "Bearer ВАШ_ТОКЕН",            "Content-Type": "application/json",            "Accept": "application/json"        },        "request_body": {},        "comment": "last_prices",        "interval": "1min",        "file_save_mode": "rewrite",        "file_format": "json",        "json_key": "lastPrices"    }

Обратите внимание — помимо того, что request_method теперь принимает значение POST, также значения в полях request_headers и request_body обрамлено в фигурные скобки.

Сохраняемся (Ctrl+S) и тестируем (F9)

Итог

Хочу повторить, что “Архивист” является промежуточным продуктом моей работы. Будет ли он развиваться, или так и останется на уровне MVP — зависит от его востребованности как на github, так и здесь. Так что если вам понравилась реализация — напишите пожалуйста, плюс буду признателен за идеи по улучшению.

ссылка на оригинал статьи https://habr.com/ru/articles/1025980/