Как писать код, если ты аналитик, или ETL своими руками
Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті
Всем привет! Меня зовут Макс, и я продуктовый аналитик в Genesis. Последние пару лет работаю как аналитик в отечественном IT. До этого несколько лет учился и работал в Европе.
В статье расскажу о том, как собрать на коленке решение, которое позволит достать данные, изменить их и перенести с помощью кода (ETL), и о том, как на похожие простые решения опираются большие продукты. Может быть полезно начинающим не-разработчикам: аналитикам, маркетологам, продуктовым менеджерам и, отдельно, поклонникам Excel.
Процессы по переносу и изменению данных называют ETL-процессами (Extract Transform & Load), а решения для них — ETL-пайплайнами (pipelines). Такие решения включают в себя извлечение данных из источников, где на них неудобно смотреть, их агрегацию и обработку, а также загрузку в хранилища. Неплохая статья об ETL есть на «Хабре».
Какие решения требуют щепотки кода или полной автоматизации
Вне зависимости от размера компании, сложности задач и опыта аналитика, у специалиста иногда возникают срочные задачи, которые предполагают автоматизацию. Среди задач, которые порой прилетают аналитикам без опыта программирования:
- Автоматизировать доставку отчетов с высокоуровневыми метриками нескольким отделам по утрам.
- Распарсить гугл-таблички с ответами участников конференции. Сделать решение масштабируемым (у компании за год — 20 конференций). Связать ответы между собой и с данными от клиентов. Сохранить результат в удобном месте и визуализировать.
- Представить несколько ключевых метрик и инсайтов, предварительно вытащив данные из разных мест (по API, из облачного хранилища, добыв и расшифровав файл, хранившийся у коллеги на компе, обратившись в БД и так далее).
- Настроить систему уведомлений о состоянии баланса на внешнем сервисе отправки сообщений в вайбере. После реализации первой части создать визуализацию с динамикой затрат по часам.
- Автоматизировать сбор агрегированных таблиц в базе данных. Добавить логирование и настроить набор действий в случае, если часть агрегаций не собралась.
Большинство задач такого типа можно выполнить не выходя из дома, имея под рукой маленький удаленный сервер и будучи знакомым со Stack Overflow.
Инструменты для автоматизации задач
Выбор таких инструментов будет зависеть от текущих задач и от того, где будет выполняться код.
- Наиболее популярное решение — Python. Хорошо применять для работы с данными, автоматизации задач на сервере и на личном компьютере. Плохо подходит для запуска на чужих машинах (попытки создать домашнее решение для импорта/превращения данных на чужих компьютерах на каком-либо языке программирования часто заканчиваются провалом).
- Хороший и менее популярный инструмент аналитиков — R. Используют для тех же целей, что и Python, но субъективно R требует больше усилий для прототипирования и отладки простых программ (для джуна, если он, например, не имел раньше опыта ни с Python, ни с R).
- Иногда можно встретить на JavaScript (или Google Script), которые позволяют вытаскивать данные в удобном виде в Google Sheets. Можно автоматизировать бесплатно на ресурсах Google и доставать информацию из баз данных/по API/из самих Google таблиц, попутно отправляя в чаты/на электронные почты оповещения об успехах (отправлять можно даже отдельные простые метрики). Такие решения не сильно популярны и имеют ряд ограничений.
- Макросы в Excel. Отдельный способ достать данные из хранилища и визуализировать прямо в Excel-файле. Хороший способ доставить данные коллегам на их локальные машины. Плохой с точки зрения контроля качества данных, на основе которых принимаются решения. Подход имеет ряд ограничений, но есть и безусловное преимущество: поскольку масштабировать его невероятно сложно, а надёжность не сравнима ни с чем, поддержка таких решений, которые остались от предшественников, — явление редкое :)
В конечном итоге выбор инструмента для автоматизации тех или иных задач всегда остается за разработчиками. А те, в свою очередь, склонны выбирать тот, с которым знакомы лучше всего, и это отличный подход, потому что он существенно экономит время.
ETL на коленке
В качестве примера простого ETL-pipelin-а напишем небольшой кусочек кода, в котором обратимся к внешнему сервису с открытыми данными, изменим их, отправим себе в любимый мессенджер и сохраним. В нашем примере, внешним сервисом будет интернет-банк, к которому можно обратиться по API, допустим, Mono. Мы будем получать (по утрам) курс валют, отправлять его себе в телеграм-канал и записывать данные в свою же гугл-табличку.
Попробуем реализовать это сначала на Python на своем компьютере. Если вы никогда ничего у себя локально на Python не запускали, стоит предварительно ознакомиться с инструкциями, как его установить, и добавить зависимости (библиотеки), которые нам в дальнейшем пригодятся. Для этого очень советую Flask tutorial. А весьма простой подход решать проблемы при разработке собственных программ — находить решения похожих проблем на Stack Overflow.
Шаг первый. Достанем и отобразим данные, которые наш банк готов отдать:
# импортируем необходимые библиотеки Python import json from urllib import parse, request # Предоставленный банком адрес URL = "https://api.monobank.ua/bank/currency" # Выделим, расшифруем и выведем в консоль полученную информацию content = request.urlopen(url=URL).read() content_decoded = json.loads(content.decode("utf-8")) print(content_decoded)
Если всё прошло успешно, в командной строке увидим список интуитивно непонятных записей. Та часть, которая нас интересует, выглядит примерно так:
{'currencyCodeA': 840, 'currencyCodeB': 980, 'rateBuy': 25.0, 'rateSell': 26.0}
Здесь находятся ISO-коды валют, стоимость покупки и продажи по состоянию на сегодня. Курс доллара к гривне идет первым элементом — с ним и будем работать дальше*.
*Доставать данные из списка по их порядковой позиции — плохая практика. Никто не гарантирует, что завтра первым элементом не будет другая валюта или другие данные. Хороший подход — превращать данные, например, в хеш-таблицу и доставать только интересующие вас записи (а если не вышло, явно отдавать ошибку).
Шаг второй. Отправим себе в телеграм-чат полученные данные. Здесь предварительно нужно создать нового телеграм-бота и получить его токен (инструкция). А также добыть Chat ID — идентификатор чата, в котором мы хотим видеть сообщения от бота*:
# Оставим в константах токен telegram бота и chat id TOKEN = "bot111222333:ABGxsjr-Abracadabra_U5aALnmu-cCern" CHAT_ID = 777888999 # Приведем нашу строку с курсом к дружелюбному виду target_note = content_decoded[0] message = f"Currency {target_note['currencyCodeA']} to " \ f"{target_note['currencyCodeB']} rate: \n " \ f"rate buy: {target_note['rateBuy']} \n " \ f"rate sell: {target_note['rateSell']}" # Сформируем запрос и отправим сообщение себе в чат bot_url = f"https://api.telegram.org/{TOKEN}/sendMessage?» \ f«chat_id={CHAT_ID}&text={parse.quote(message)}&parse_mode=html" request.urlopen(bot_url)
*Узнать Chat ID всех собеседников бота можно с помощью браузера, обратившись в адресной строке к https://api.telegram.org/<YourBotToken>/getUpdates
.
Успешным результатом этого шага будет доставленное сообщение в телеграм-чат:
Шаг третий. Внесем полученные данные в Google Sheets. Для этого надо установить внешние зависимости и получить service account key из Google-консоли.
Внешние зависимости установим, выполнив в консоли:
pip3 install gspread oauth2client
Инструкцию по генерации ключа доступа к сервисам Google здесь приводить не буду — её можно найти в документации к установленной библиотеке gspread. Сам же код будет выглядеть следующим образом:
# Импорт установленных библиотек import gspread from oauth2client.service_account import ServiceAccountCredentials # Объявим, с какими сервисами будем работать scope = ['https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive'] # Авторизуемся со своим Service Account Key client = gspread.authorize(ServiceAccountCredentials.from_json_keyfile_name( 'credentials.json', scope)) # Обозначим, к какому документу мы обращаемся doc_name = 'test sheet' sheet = client.open(doc_name) worksheet = sheet.worksheet('Sheet1') # И запишем данные в саму google-таблицу worksheet.append_row(['Сurrency ISO', 'Сurrency ISO', 'Buy rate', 'Sell rate']) worksheet.append_row( [target_note['CurrencyCodeA'], target_note['CurrencyCodeB'], target_note['rateBuy'], target_note['rateSell']])
Если всё прошло успешно, мы увидим вот такую запись в своей гугл-табличке:
Полностью весь скрипт можно найти на GitHub*.
*Если решение выглядит не самым полезным, но вы хотите его как-то использовать — можно доставать по API из банка состояние своего счёта и затраты за последние сутки.
Итак, что мы реализовали выше:
- достали интересующие нас данные по API из стороннего сервиса (Extract);
- отфильтровали и привели в читабельный вид (Transform);
- отправили себе в чат и положили на хранение в табличку (Load).
Наш ETL-инструмент состоит исключительно из скрипта, который выполняет основную работу. Но в бизнесе хорошие технические решения часто содержат в себе не только core-фичу, которая выгружает, изменяет и сохраняет данные, но и несколько дополнительных полезных компонентов:
- панель управления, которая позволит менять поведение инструмента, не меняя его код;
- хранилище логов, где можно ретроспективно посмотреть на успешность работы сервиса;
- система алертов, которая оповещает нужных сотрудников о том, что сервис не отработал или получил аномальные данные.
Сложно ли автоматизировать такой маленький воркер
Не все сервисы нуждаются в автоматизации. Так, если у вас нет уверенности, что работа воркера будет актуальной больше недели — вполне нормально несколько раз запустить его со своего компьютера.
Если работа сервиса важна и полезна — лучше перенести код на сервер и автоматизировать его запуск. С этим может помочь девопс, а если такового нет, то сидящий ближе других разработчик.
Технически автоматизация не требует много времени. Выполнение нашего кусочка кода по расписанию на Linux-сервере займёт одну строку в cron-файле, на сервере с Windows — одну запись в планировщике задач.
Нужна ли документация для простых решений
Если коротко, то очень нужна. Если вы написали 20 строк кода и запускаете его по утрам, то в своей Wiki/Confluence/внутреннем Stack Overflow стоит простым языком вкратце описать возможности сервиса, его ограничения и к кому обратиться, если нужно будет чего-то подправить. Кроме того, хорошо будет добавить небольшую заметку для будущих разработчиков, которые займутся поддержкой сервиса (они вам будут благодарны). Отличный вариант для этого — залить код в любую используемую в вашей компании систему контроля версий с комментариями или readme-файлом.
Зачем на это тратить время? Так гораздо больше шансов, что ETL будет передан на поддержку другому специалисту при переходе сотрудника на другие проекты/компанию. Также это хороший повод ответить на вопросы, почему те или иные «костыли» были созданы, а это, в свою очередь, позволит учиться на архитектурных ошибках самому и передать немного знаний коллегам-джунам.
Какие решения можно автоматизировать ещё
Приведенный пример (работа с API, мессенджером и гугл-таблицей) не будет самым распространённым ETL-процессом. Такие процессы, скорее всего, будут связаны с базами данных и предусматривать изменения в них самих или выгрузку из них чего-либо. После этого полученную информацию нужно будет визуализировать и доставить такую визуализацию коллегам. Хорошими примерами (и задачами для автоматизации) могут быть:
- задачи по агрегации данных в БД (формированию табличек с агрегированными метриками в нескольких разрезах, для того чтобы использовать их, а не таблицы с сырыми данными — очень экономит ресурсы);
- перелив в БД информации из внешних источников (по API, используя native tools для облачных решений);
- перенос данных между таблицами/базами;
- выгрузка данных из базы в удобном виде в Google Sheets для визуализации;
- алерты при резких изменениях любых метрик, которые можно посчитать в базе данных;
- сообщения в чат по утрам о состоянии продукта;
- выгрузка Tableau-отчётов в Slack/Telegram/любимый мессенджер/на почту шефу каждый час, день или неделю (да, и у систем визуализации есть свой API).
Несмотря на то, что мощности серверов (и своих, и арендованных) почти всегда чего-то стоят, маленький дополнительный воркер они могут вытащить без существенных дополнительных затрат. Потому стоимость таких простых решений (в тех случаях, когда они не отрабатывают часами, переливая миллионы строк) определяется стоимостью вашей part-time работы.
Summary
В нашем примере мы реализовали простой ETL-процесс, который умеет доставать информацию из стороннего сервиса, отправлять оповещение и сохранять данные. Такие простые решения работают даже в самых успешных компаниях. Почему? Потому что процессы, которые на таких сервисах построены, не так уж часто ломаются, если они просты и атомарны.
Насколько они должны быть просты:
- джун сможет понять, нагуглить решение и поправить код;
- если вы уйдете из компании через две недели, такое решение сможет проработать еще два года (пока условный фейсбук не обновит в очередной раз свой API);
- после того как сервис поломается, алерты в ваш чат будут лететь, пока не почистят от кода сервер (потому что сервис уведомлений имеет запас прочности, как гаечный ключ).
Про другие (более взрослые) ETL-решения можно почитать у ребят из Google (про то, как сделать всё на свете на их ресурсах), в блоге Netflix и на «Хабре».
Буду рад комментариям и фидбэку :)
3 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів