В одном из проектов возникла необходимость перевести процессы импорта данных сторонних систем на микросервисную архитектуру. В качестве инструмента выбран Apache NiFi. В качестве первого подопытного выбран импорт ЕГРЮЛ ФНС.
Шаг первый — загрузка файлов. Предполагался FTPS, а оказался HTTPS…
Источник данных
Получение данных из ЕГРЮЛ осуществляется в рамках услуги ФНС «Интеграция и доступ к базам данных ЕГРЮЛ и ЕГРИП». Описание модели взаимодействия представлено здесь.
Данные предоставляются в виде XML-файлов, упакованных в ZIP-архивы. Архивы ежедневно выкладывают на сервер в отдельный каталог для соответствующей даты. Для доступа к серверу выдается ключ #PKCS12. В описании указано, что это FTP-сервер. Но по FTP подключиться почему-то не удалось. Да и все пути ведут именно к ресурсу https://ftp.egrul.nalog.ru/, и естественно он благополучно открывается в браузере.

Настройка DataFlow в Apache NiFi
DataFlow должен выполнять следующие операции:
1. Генерация ссылки на каталог с вчерашней выгрузкой — процессор GenerateFlowFile
2. Получение содержимого каталога — процессор InvokeHTTP
3. Получение ссылок на файлы архивов — процессор GetHTMLElement
4. Получение архивов — процессор InvokeHTTP
5. Распаковка архивов — процессор UnpackContent.

Генерация ссылки на каталог с вчерашней выгрузкой
Для генерации ссылки используется процессор GenerateFlowFile.

Он запускается каждые 24 часа и создает FlowFile с атрибутом fnsEgrulURL, в который записывается значение выражения NiFi Expression Language:
${literal('https://ftp.egrul.nalog.ru/?dir=EGRUL/'):append(${now():toNumber():minus(86400000):format('dd.MM.yyyy')})}
На выходе генерируетсяFlowFile следующего вида.
Получение содержимого каталога
Для получения содержимого каталога используется процессор InvokeHTTP. Он выполняет GET-запрос по ссылке, сгенерированной предыдущим процессором. В ответ процессор получает HTML-код страницы каталога с выгрузкой за вчерашнюю дату и добавляет этот HTML-код в FlowFile в качестве контента.
Процессор имеет следующие настройки:
HTTPMethod — метод GET;
Remote URL — выражение ${fnsEgrulURL}, т.е. значение берется из FlowFile из атрибута fnsEgrulURL;
SSL Context Service — необходимо создать контроллер типа SSLContextService или StandardRestrictedSSLContextService и настроить его для обращения к сайту ФНС через HTTPS.
Остальные параметры оставлены по умолчанию.
Контроллер SSLContextService
В настройках котроллера SSLContexService необходимо указать путь и пароль к файлу ключа #PKCS12 и путь и пароль к хранилищу доверенных сертификатов, в котором размещен промежуточный сертификат из цепочки сертификатов, используемых при взаимодействии с ресурсом ФНС.
В качестве хранилища доверенных сертификатов использовано хранилище cacerts из состава JDK. В него необходимо импортировать промежуточный сертификат. Для получения промежуточного сертификата необходимо открыть страницу https://fns.egrul.nalog.ru в браузере, использовав ключ #PKCS12. В адресной строке нажать иконку защищенного соединения и открыть сертификат.

В цепочке сертификата необходимо выбрать сертификат Russian DPC Tax Service и экспортировать его в формате .CER в кодировке DER. Далее необходимо импортировать сертификат из полученного файла в хранилище cacerts c помощью утилиты keytool. Например, так:
C:\Program Files\Java\jdk1.8.0_121\bin> keytool -importcert -keystore "C:\Program Files\Java\jdk1.8.0_121\jre\lib\security\cacerts" -file {Путь к файлу .CER}
Пароль к cacerts по умолчанию — changeit.
Далее файл ключа и cacerts необходимо расположить там, где NiFi будет иметь к ним доступ. Например, в Persistent Volume. Соответствующие пути необходимо указать в параметрах контроллера SSLContextService. Там же для ключа необходимо указать тип PKSC12, а для cacerts — тип JKS.
Процессор InvokeHTTP добавит в FlowFile атрибуты, содержащие параметры запроса и ответа, и контент — HTML-код запрошенной страницы.
Получение ссылок на файлы архивов
Получение ссылок на файлы архивов выполняется процессором GetHTMLElement, который извлекает содержимое требуемого HTML-элемента из контента FlowFile-а. В данном случае нам требуется получить ссылки на ZIP-архивы.
<div id="page-content" class="container"> <div id="directory-list-header"> <div class="row"> <div class="col-md-7 col-sm-6 col-xs-10">Файл</div> <div class="col-md-2 col-sm-2 col-xs-2 text-right">Размер</div> <div class="col-md-3 col-sm-4 hidden-xs text-right">Последнее изменение</div> </div> </div> <ul id="directory-listing" class="nav nav-pills nav-stacked"> <li data-name=".." data-href="https://ftp.egrul.nalog.ru/?dir=EGRUL"> <a href="https://ftp.egrul.nalog.ru/?dir=EGRUL" class="clearfix" data-name=".."> <div class="row"> <span class="file-name col-md-7 col-sm-6 col-xs-9"> <i class="fa fa-level-up fa-fw"></i> .. </span> <span class="file-size col-md-2 col-sm-2 col-xs-3 text-right"> - </span> <span class="file-modified col-md-3 col-sm-4 hidden-xs text-right"> 2020-04-05 22:00:00 </span> </div> </a> </li> <li data-name="EGRUL_2020-04-05_1.zip" data-href="EGRUL/05.04.2020/EGRUL_2020-04-05_1.zip"> <a href="EGRUL/05.04.2020/EGRUL_2020-04-05_1.zip" class="clearfix" data-name="EGRUL_2020-04-05_1.zip"> <div class="row"> <span class="file-name col-md-7 col-sm-6 col-xs-9"> <i class="fa fa-file-archive-o fa-fw"></i> EGRUL_2020-04-05_1.zip </span> <span class="file-size col-md-2 col-sm-2 col-xs-3 text-right"> 528.78KB </span> <span class="file-modified col-md-3 col-sm-4 hidden-xs text-right"> 2020-04-05 22:00:24 </span> </div> </a> <a href="javascript:void(0)" class="file-info-button"> <i class="fa fa-info-circle"></i> </a> </li> </ul> </div>
Параметры процессора:
URL — базовый URL обрабатываемой HTML-страницы;
CSS Selector — селектор для выбора интересующего нас элемента. li[data-name^=EGRUL] — элемент li, который содержит атрибут data-name, значение которого начинается с EGRUL;
Output Type — Attribute — данные будут извлечены из атрибута HTML-элемента;
Destination — flowfile-attribute — результат будет помещен в атрибут FlowFile-а (атрибут всегда называется HTMLElement);
Attribute Name — данный параметр описывает, какое значение должно быть получено в результате. abs:${literal('data-href')} — базовый URL + значение атрибута data-href для элемента, найденного CSS-селектором.
Для каждого элемента, найденного CSS-селектором будет создан отдельный FlowFile.
Получение архивов
Для получения архивов с файлами выписок ЕГРЮЛ используется процессор InvokeHTTP. Его настройки аналогичны процессору InvokeHTTP для получения HTML-кода страницы. SSLContextService используется тот же самый. Запрашиваемый URL берется из FlowFile-а из атрибута HTMLElement, т.е. — ссылка на ZIP-архив.
Процессор скачивает ZIP-архив по ссылке из атрибута HTMLElement и помещает его в FlowFile в качестве контента.
Распаковка архивов
Для распаковки архивов используется процессор UnpackContent. В параметрах процессора достаточно выбрать только тип архива — ZIP.
На выходе процессор создает FlowFile для каждого XML-файла, распакованного из ZIP-архива.
Далее…
Далее каждый XML требуется преобразовать в JSON и разбить его по организациям, т.к. каждый XML содержит от 1 до 1000 выписок ЕГРЮЛ. А из JSON уже в дальнейшем можно будет загрузить данные в SQL или NoSQL хранилище.
О преобразовании XML в JSON и о AVROSchema — в следующей статье.
ссылка на оригинал статьи https://habr.com/ru/post/496900/
Добавить комментарий