16 заметок с тегом

программирование

Как работает очистка данных со stat.gibdd.ru

Год назад написал скрипты для очистки данных статистики ДТП, потому что изначальные данные (именно GPS-координаты) были очень грязными и их практически нельзя было визуализировать. Сорцы на Гитхабе имеются.

Сейчас скрипты временно неработоспособны, так как Яндексовский геокодер теперь требует ключ для использования API, но скоро я их поправлю.

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

Алгоритм очистки данных

Описаниме по шагам

Изначально нам дана синяя точка слева внизу. Это GPS-координаты, которые мы получили из исходных данных. Наша основная зацепка — адрес. Он заполняется вручную и обычно верный.

Шаг 1. Воспользуемся геокодером. Это такая программа, которая переводит географическое название (город/село/улицу + дом) в географические координаты. Я обычно пользуюсь геокодером Яндекса, потому что он точнее для СНГ, но ещё есть бесплатный от OpenStreetMap. Так мы получаем чистую координату дома по адресу (красная точка на рисунке).

Шаг 2. В OSM хранится граф дорог, при этом они привязаны к географическим координатам (у графа есть точное положение на плоскости). И есть классная особенность: мы можем ввести координаты точки на плоскости и получить кусок графа в радиусе n от этой точки. Общая идея такая:

  • вводим координаты дома после геокодирования -> получаем круг примерно как на картинке,
  • выбираем все дороги, попавшие в радиус (можно считать их просто линиями),
  • строим перпендикуляры из точки до каждой из линий (на рисунке x и y),
  • выбираем кратчайший (в нашем случае x),
  • наша красная точка получает новые координаты (уже на ребре графа из OSM) и становится жёлтой точкой,
  • profit.

Так мы кривые координаты ДТП по одному лишь адресу аккуратно перенесли прямо на улицу. Теперь при визуализации всё будет аккуратно и ровно.

Датасет структуры сети Lightning

Ковыряю в свободное время интересную тему и задачу, которую курирует LAMBDA.

Вводная

Есть сеть Лайтнинг, которая является надстройкой над майннетом Биткоина. Придумывалась для более мелких транзакций, которые не позволял делать Биткоин. Например, тебе нужно заплатить за кофе или совершить какую-то маленькую операцию.

Основная терминология:

  • нода — узел сети. Получатель денег в общем,
  • канал — ребро сети. Общий кошелёк в майннете Биткоина между двумя нодами.

В Лайтнинге интересный механизм поиска пути транзакции. Eсли тебе надо перевести деньги из А в С, то не обязательно открывать новый общий кошелёк в майннете Биткоина.

Предположим у тебя уже есть канал А<->B и есть канал B<->C. В таком случае ты можешь сделать перевод A->B->C, где B за проход транзакции через себя возьмёт какую-то комиссию. А можно перевести и предположим по пути A>D->B->C, если такой существует.

Но не всё так просто. Помимо комиссии, на транзакцию накладываются дополнительные условия. У канала есть «ёмкость»: сколько можно переслать денег между двумя нодами без создания нового общего кошелька в майннете. И «ёмкость» А->B и B->A не одно и то же.

Подробнее и больше можно почитать в документации.

Цель

Основная идея ресёча — заменить глупый перебор результатов DFS для проведения транзакции на что-то более умное. Кажется, что это можно сделать, имея статистику «прошедших» транзакций и варианты альтернативных путей. Получиться должно что-то вроде статистического роутинга на основе прошлых транзакций.
Для этого нужно собирать датасет таких транзакций и их альтернатив, но это упирается в некоторые технические сложности и проблемы. Я собственно сейчас пытаюсь их решить, проверяя вообще работоспособность идеи сбора таких данных. Если получится, то будет очень классное и необычное решение.

Датасет

До этого этапа хотелось посмотреть (и посмотрели) просто на динамику сети, как она меняется и насколько стабильна. Написал простенький парсер и в итоге получился датасет на 10 Gb «слепков» сети: рёбра графа и всякая метаинфа нод (ip-адрес, алиас в сети и гео-координаты).

Парсилось каждый час с 10.12.2019 до 04.03.2020 (84 дня), всего 2022 записи. Каждый результат в отдельном файле со своим временем.

На этом датасете можно построить интересные визуализации динамики графа и прочие клёвые штуки. Почему бы собственно им не поделиться, да?

 Нет комментариев    188   1 мес   анализ данных   программирование   проекты   ресёч

«Средненько». Проверка гипотезы

Мотивация

Я 3-4 года назад услышал про исследование КБ «Стрелка», в котором они скрапили фото из социальных сетей (Инстаграм и ВК) и рисовали хитмапы на картах по ним. Оказывается, это называется цифровой антропологией.

Идея кейса, который вдохновил меня, в том, что такое исследование помогло в каком-то там городе РФ выбрать лучшую точку для открытия общественного пространства. Гипотеза такая: если люди где-то делают фото, значит уже проводят там время, а значит там и так всё хорошо с социальной жизнью. В итоге администрации посоветовали открыть новую точку интереса на противоположном конце города от существующей.

Загорелся идеей сделать нечто похожее, но в сферу каких-то постоянных событий идея оставалась идеей без реализации.

Закрывая гештальт (как Инстаграм своё API для доступа к гео-информации о фотографиях в 2016-ом) достиг успеха.

Реализация

Т. к. API Инстаграма оказалось закрытым, решил воспользоваться Flickr’ом.
Суть идеи:

  • берем 2019ый год,
  • cкрапим фотографии с Flickr для конкретной локации (т.e. города),
  • аккуратно накладываем на карту,
  • видим места, где люди много фотографируют,
  • делаем какие-то выводы.

Например: люди фотографируют -> там что-то интересное -> логично поселиться во время поездки.

Другой например: можно увидеть места, которые недостаточно освещены туристически (с точки зрения наличия фотографий) и можно выбрать наоборот район, где живут местные. На примере Берлина эта теория вроде как работает.

Фотографии в Берлине за 2019ый год

Найденные подводные камни:

  • API Flickr’a частично не завелось из python-обертки, которую я нашёл,
  • фотографий не так много (250к за год), как в Инстаграме. С геопозицией — еще меньше. За 2019ый год только 44к для Берлина,
  • на карте прямыми линиями из фотографий заметны фотопрогулки, когда один человек шел и фотографировал всё, что видел. Так получается много фотографий одного места, хотя это всего лишь от одного человека. В планах написать кастомную функцию хитмапа, которая бы давала больший вес участкам, где фотографии от разных людей. Так получится сильно честнее.

«Средненько»

В процессе возникла идея — сопоставить кучу фотографий одной достопримечательности для получения её «усреднённого» вида. Итог получился сильно лучше, чем я ожидал.

Оригинальные Бранденбургские ворота
Усреднённые 55 фотографий Бранденбургских ворот

Когда-то вероятно продолжу и сделаю для других городов.

Ecto и GCP Cloud SQL

Когда запускаешь сервис через GCP Cloud Run, есть очень удобная возможность пробросить внутрь контейнера Cloud SQL через настройки сервиса при запуске.

В Ecto (data-layer для Elixir-приложений, чаще всего используется с фреймворком Phoenix) получается такой удобный конфиг для PostgreSQL:

# project_directory/config/config.exs config :project, Project.Repo, username: "username", password: "password", database: "db_name", socket: "/cloudsql/<project>:<region:><db_instance_name>/.s.PGSQL.5432"
 Нет комментариев    84   2 мес   elixir   gcp   phoenix   полезности   программирование

docker-compose не умеет искать конфиги docker’a из snap’a

Исходная обстановка:

docker version 18.09.9, build 1752eb3 docker-compose version 1.25.4, build 8d51620a Ubuntu 18.04

При пуле из приватного AWS ECR после docker login и aws ecr get-login-password сам docker работает нормально, а вот docker-compose не может аутентифицироваться в ECR и отдает ошибку:

ERROR: compose.cli.errors.log_api_error: Get https://aws_id.dkr.ecr.region.amazonaws.com/image:tag: no basic auth credentials

Через verbose выяснено, что docker-compose ищет конфиг с ключами в ~/.docker/config.json или ~/.dockercfg, а если (как было и есть у меня) docker поставлен через snap, то конфиг благополучно не находится, потому что всё лежит в другом месте. Спасибо на том, что в verbose пишет.

Конфиг же лежит в ~/snap/docker/current/.docker/config.json, где current — это симлинк до текущей версии.

Выход: создать симлинк на существующий конфиг в ~/.docker/

UPD: Хотя да, тут можно и в мейнтейнеров пакета из Canonical камень кинуть, почему они симлинки конфигов в стандартные места не делают при установке. Кажется разумным так делать.

 Нет комментариев    85   2 мес   полезности   программирование

bash -> zsh

Ruby-скрипт для конвертации истории bash в zsh, Ctrl-C / Ctrl-V с просторов Гитхаба.

#################################################################
# = This script transfers bash history to zsh history
# = Change bash and zsh history files, if you don't use defaults
#
# = Usage: ruby bash_to_zsh_history.rb
#
# = Author: Ankit Goyal
#################################################################

# change if you don't use default values
BASH_HISTORY_FILE_PATH="#{ENV['HOME']}/.bash_history"
ZSH_HISTORY_FILE_PATH="#{ENV['HOME']}/.zsh_history"

# Read the bash history file
bash_hist_file = File.read(BASH_HISTORY_FILE_PATH)

# Get the list of commands from bash history hile
command_list = bash_hist_file.split("\n")

# Open the zsh history file
zsh_hist_file = File.open(ZSH_HISTORY_FILE_PATH, "a")

# Get timestamp required for zsh history file format and update the history file
time = Time.now.to_i
command_list.each do |command|
  time += 1
  zsh_hist_file.write(": #{time}:0;#{command}\n")
end

# Close the file
zsh_hist_file.close
 Нет комментариев    53   3 мес   полезности   программирование
 Нет комментариев    159   5 мес   образование   программирование

[Идея] Авто-плейлист Spotify/AppleMusic из ближайших концертов в твоём городе

Хочу следующий флоу:

  • сервис парсит артистов и их концерты в  с заданного списка сайтов и формирует тебе плейлист,
  • ты слушаешь плейлист и если тебе понравилась группа/трек, то идёшь на веб-страницу, смотришь концерт этой группы и покупаешь билеты,
  • когда концерт прошёл — трек удаляется из плейлиста.

Выглядит как автоматический мониторинг ближайших концертов прямо в ушах.

Возможность потыкать API Spotify/AppleMusic/GooglePlayMusic.

 Нет комментариев    250   7 мес   идея   программирование   проекты

[Идея] Бот в Telegram, который мониторит просмотры поста в realtime

Было бы классно заиметь бота, который будет подписан на канал и проверять каждые несколько секунд количество просмотров поста.

Получится лучше понять аудиторию, кто когда смотрит посты. У меня есть предположение, что некоторые люди вечером открывают список каналов и смотрят все новости за день. Интересно, сколько таких. Ещё можно мониторить чужие каналы и наблюдать за их подписчиками.

По этим данным нужно построить красивые графики, чтобы сидеть и смотреть на них. Красота.

 Нет комментариев    277   8 мес   идея   программирование

Особенности pip и потенциальная дырка

Не вдаваясь конкретно в библиотеки (это два клиента для keycloak), расскажу о ситуации.

Есть библиотека А и библиотека B. Библиотеки А и  B обе зарегистрированы в pypi под разными именами. Но в setup.py обе экспортируют одинаковые по имени пакеты (параметр packages), которые и буду в итоге отображены в вашем списке пакетов. Как вы думаете, как поступит pip, если указать ему обе библиотеки в зависимостях проекта?

... минутка на подумать ...

Он их смёржит между собой. При этом будет устанавливать одну библиотеку поверх другой, в порядке как в списке зависимостей. Я не нашёл ни в документации ни где-то ещё описания такого поведения. А оно приводит например к следующему:

  • у вас в списке зависимостей библиотека A идёт перед библиотекой B,
  • и там и там есть файл exceptions.py, в котором прописаны исключения,
  • после установки библиотеки B, файл exceptions.py будет из библиотеки B, при этом уникальные для библиотеки А файлы так и останутся на месте и в импортах будет использоваться exceptions.py, который уже от другой библиотеки,
  • как минимум это приводит к конфликтам, ошибкам и дебагу.

Ещё интересным выглядит вектор раскручивания этого до уязвимости: а что, если мы в нашей библиотеке (или в зависимостях нашей библиотеки) пропишем какое-то популярное имя пакета (например Flask) и переопределим поведение? Т.e. любой, кто установит нашу библиотеку не глядя на то, что внутри, имеет шанс запустить у себя наш код не подозревая об этом. Достаточно просто нашу библиотеку в списке зависимостей разместить ниже фреймворка, в который мы лезем.

Мем конечно смешной, а ситуация страшная.

Решил сходить и спросить у знающих людей, как так можно жить. Никита Воронов делает dephell и рассказал, что это не баг, а фича.

Так можно делать отдельные пакеты с плагинами, которые положат себя в папку plugins. Причём много кто это делает, так что поведение уже поздно менять. Про опасность пакетов вообще бесполезно говорить. Уже при установке пакет может в setup.py что угодно сделать. Например, слить твой ssh ключ. Так что недоверенные пакеты устанавливать вообще нельзя. Можно почитать, почему никогда нельзя звать sudo pip install. Проблема в том, что альтернатив нет, а все другие пакетные менеджеры (в том числе и dephell) всё равно внутри зовут pip.

Всё это грустно. Ну и надо думать над тем, как называть пакеты и смотреть, есть ли кто-то уже с таким же именем в pypi. Для решения моего конфликта оказалось проще руками затащить часть одной из либ в проект. Другой найденный вариант — использовать install-options pip’a и prefix для задания кастомного пути одной из либ.

Ну и конечно устанавливайте только доверенные пакеты.

 Нет комментариев    294   9 мес   питон   программирование
Ранее Ctrl + ↓