CoderCastrov logo
CoderCastrov
Covid-19

Отслеживание COVID-19 в Квебеке - небольшой квест

Отслеживание COVID-19 в Квебеке - небольшой квест
просмотров
7 мин чтение
#Covid-19

Предисловие

Все началось, как обычно, с простой идеи. Что-то, чтобы скоротать время, чтобы держать ум в работе. Это началось с одной вещи. Одной задачи. Но это не оставалось таким надолго.

Введение

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

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

Все это говорит о том, что, даже будучи безработным, у меня далеко не хватает свободного времени. Но это не значит, что я не попытаюсь реализовать личный проект. И для этого проекта я собирался улучшить визуализацию развития COVID-19 в Квебеке, Канада. Хотя официальный сайт правительства содержит множество информации, у него нет исторических изменений - технически называемых "Накопленные случаи по данным эпизода", только последнее число подтвержденных случаев и разбивка случаев и смертей по регионам и возрастным группам - в виде таблиц, далеко не лучший способ визуализации такой информации.

Небольшое замечание здесь: когда я начал этот проект, в Квебеке было всего несколько подтвержденных случаев, и ни одно СМИ не предоставляло информацию в виде инфографики. К тому времени, когда я наконец смог закончить его, большинство крупнейших СМИ имели такую графику в той или иной форме. Особенно хорошо сделана графика от ICI-Radio-Canada. Тем не менее, я хотел попробовать свои силы, побороться с кодированием этого приложения и извлечь из него уроки.

Проект

Проект сосредоточен на бэк-энде и имеет небольшую часть фронт-энда. Вот инструменты, которые я использовал:

  • NodeJS с Express
  • Express CORS
  • Puppeteer — для парсинга веб-страниц Квебека и Канады
  • MongoDB для хранения данных
  • amCharts для создания графиков
  • Vanilla HTML/CSS/JS

Вы можете проверить результат здесь: https://qc-covid19-tracker.herokuapp.com/

И вы можете проверить исходный код здесь: Основное приложение Приложение парсера

Я изучал как MongoDB, так и amCharts для другого, более крупного проекта, но в этот раз впервые применил их на работающем коде. Puppeteer — или парсинг в целом — был для меня полностью новым, и много времени и усилий в этом проекте было потрачено на его изучение.

Структура проекта довольно проста. Парсер получает последнюю информацию с официальных веб-страниц Квебека и Канады и сохраняет эти данные в базу данных MongoDB. Сервер получает данные из базы данных и передает их на фронт-энд. Фронт-энд обрабатывает информацию, создает графики и заполняет текстовые элементы — все это отображается одновременно. Во время получения и обработки данных отображается простая анимация загрузки.

Когда я приступил к созданию этого приложения, уже было зарегистрировано несколько дней с подтвержденными случаями в Квебеке. Поэтому первые несколько дней данных были получены с помощью Wayback Machine Интернет-архива. С момента настройки парсера и подключения сервера к базе данных MongoDB, все данные ежедневно получаются с официального веб-сайта правительства и добавляются в базу данных.

О радостях парсинга

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

Моя первая версия парсера была довольно простой: она парсила общее количество случаев с веб-страницы Квебека. Когда она заработала, я приступил к написанию простого сервера, чтобы использовать эту информацию на фронтенде. Веб-страница изменилась дважды, пока я писал сервер. Во-первых, она полностью переехала на новый адрес, так как правительство улучшило свой портал для предоставления информации людям. Затем она изменила структуру страницы. Первый раз было достаточно легко решить проблему, просто получить новый URL. Второй раз показал мне, насколько хрупким был мой алгоритм парсинга, основанный на XPath. Поэтому я прервал написание сервера, чтобы решить эту проблему. Здесь я получил бесценную помощь Джошуа Комо. Он показал мне, как сделать это правильно, используя селекторы, способные устойчиво справляться с небольшими изменениями страницы. Конечно, если правительство снова изменит страницу, мне придется пересмотреть свои селекторы, но это маловероятно. К тому времени, когда я нашел правильный селектор, появилась еще информация, и я ее получил.

MVP v1

Проблема с парсером решена, я написал сервер, настроил базу данных с помощью MongoDB, создал простой фронтенд на Vanilla JS и развернул его - не без трудностей, связанных с настройкой приложения Heroku. Но оно было там, чтобы увидеть весь мир.

Однако оно было неполноценным. Я быстро понял, что если официальный сайт правительства прекратит свое существование, то и мое приложение прекратит работу. Потому что я использовал базу данных только для хранения общего числа случаев по дням. Вся остальная информация, отображаемая на странице, получалась непосредственно из парсинга веб-страницы Квебека без постоянного сохранения где-либо.

Это означало, что у моего сервера было три конечные точки: одна для парсинга веб-страницы правительства, одна для сохранения общего числа случаев дня в базе данных и одна для предоставления списков общего числа случаев по дням на фронтенд. Плюс, статическая конечная точка для предоставления фронтенда. Но это еще не самое плохое. Приз за это достается тому факту, что все начиналось самим фронтендом, то есть, когда кто-то посещал страницу, начинался весь процесс. Что означало, что если страница оставалась непосещенной в тот или иной день, то данные не парсились и не записывались в базу данных в этот день, что создавало пробел в информации. И это при условии, что страница вообще работала, так как все зависело от того, чтобы веб-страница правительства оставалась примерно такой же. Хрупкая система, одним словом.

Версия 1: Некоторые данные берутся из базы данных, некоторые получаются непосредственно из парсера.

Туда и обратно

Итак, я приступил к переписыванию большей части своего приложения, чтобы улучшить его структуру и сохранять всю информацию в базе данных, так чтобы страница отображала только то, что приходит из одной единственной конечной точки; той, которая обслуживает все данные в MongoDB. Если государственная веб-страница сломается или будет удалена, у меня все равно будет данные для отображения. В то время как я переписывал все, конечно же, государственная страница снова изменилась. Ничего не сломалось, но вдруг появилось гораздо больше данных. И поскольку я добавлял строки в парсер, почему бы не написать еще один парсер, чтобы получить некоторую базовую информацию с веб-страницы Канады для сравнения?

Я сделал это. Это зеркало парсера для Квебека, только другая веб-страница и другие селекторы. У него есть несколько недочетов - он прекрасно работает в разработке каждый раз, но иногда не работает в продакшене. Чтобы защитить базу данных от записи некорректных данных, не только из-за этой неполадки, но и в случае исчезновения страниц, было проведено несколько тестов, чтобы проверить полученные данные перед их сохранением в БД.

И тогда осталось двое

В то время как все это переписывалось, следуя советам еще одного наставника, Куинна Ланжила, я решил разделить приложение на две части. Одна из них будет отвечать только за парсинг страниц обоих правительств и сохранение данных в MongoDB. Вторая будет извлекать эти данные и предоставлять их в интерфейсе. Более упрощенный процесс и лучший контроль, если (когда) официальные страницы исчезнут.

Версия 2: Два приложения, одна ответственность. Кроме того, гораздо больше данных.

Уроки

Показывать большое количество данных сложно. Показывать большое количество данных в графиках немного проще, но все равно требует много работы. Показывать большое количество данных, даже в графиках, на мобильном экране - это боль. Некоторые графики хорошо преобразуются под маленький экран, например, столбчатые диаграммы для накопительных случаев и темпа изменения. Круговые диаграммы, особенно с большим количеством секторов, становятся нечитаемыми. Я считаю, что достиг хорошего баланса, хотя уверен, что это все еще далеко от лучшего способа.

Планирование потока приложения, возможно, важнее, чем написание самого приложения. Если бы я потратил больше времени на размышления о деталях информации, я мог бы представить V2 в качестве V1.

Развертывание на Heroku на самом деле довольно просто, но вы должны быть внимательны к всем мелочам: переменные конфигурации, пути получения данных и другие вещи могут вызвать головную боль, если вы не привыкли к этому.

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