12

Вопроса пост к программистам, датасаянтистам

Товарищи, прошу посильной помощи, подсказки профи и умельцев во имя научения.


Добрый день.

"Напоролся" на ситуацию впервые, но, как я понимаю, для специалистов по BigData - вполне частая ситуация.

Хотел попробовать поработать с большим массивом данных на основе информации на портале ГосЗакупок. Данных очень много, потому показалось интересным, в том числе, в учебных целях.

Power BI не умеет работать с ftp, где расположены данные, потому пришлось искать варианты решения. Остановился на написании bat-файла, который загружает обновлённые данные c ftp на жёсткий и может обновлять: (код bat-файла, если вдруг интересно)


@Echo off

set downloadfolder="fcs_regions/Permskij_kraj/contracts/"

IF not exist %downloadfolder% (mkdir %downloadfolder%)

"C:\Program Files (x86)\WinSCP\WinSCP.com" ^

/log="D:\Code\M + DAX\ftp.zakupki.gov.ru\scp_sync_log.txt" /ini=nul ^

/command ^

"open ftp://free:free@ftp.zakupki.gov.ru/" ^

"synchronize -criteria=size -transfer=binary local ""d:\Code\M + DAX\ftp.zakupki.gov.ru\%downloadfolder%"" %downloadfolder%" ^

"close" ^

"exit"

set WINSCP_RESULT=%ERRORLEVEL%

if %WINSCP_RESULT% equ 0 (

echo Success

) else (

echo Error

)

exit /b %WINSCP_RESULT%


Всё стало лучше (так казалось), настало время подключаться к данным (а это данные, если вдруг захотите получить готовый комплект). Сформировал 3 файла: общий путь к данным, функция вы извлечения данных из архивов, набор операций преобразования данных.

В общем-то и всё. Начинаем грузить информацию. К слову говоря, делаем это на сервере, где выделяется 36 Гб оперативки и достаточная производительная мощность. Однако, в процессе загрузки (а это только часть данных) всё крашится с неведомыми ошибками. Я полагаю, что просто ресурсов не хватает. Шутка ли, загрузить в кеш 20 Гб данных в виде архивов, каждый из которых надо распаковать и всё это ещё и объединить и прочее.

Собственно, теперь вопрос. Как построить работу с таким объёмом данных и умудриться это всё обработать?


let

Источник = Folder.Files(#"Путь к папке"),

#"Полный путь к файлу" = Table.AddColumn(Источник, "Полный путь к файлу", each [Folder Path]&[Name]),

#"Другие удаленные столбцы" = Table.SelectColumns(#"Полный путь к файлу",{"Полный путь к файлу"}),

#"Измененный тип" = Table.TransformColumnTypes(#"Другие удаленные столбцы",{{"Полный путь к файлу", type text}}),

#"Контент фалйа" = Table.AddColumn(#"Измененный тип", "Контент файла", each File.Contents ([Полный путь к файлу])),

#"Вызвана настраиваемая функция" = Table.AddColumn(#"Контент фалйа", "fx_UnzipContents", each fx_UnzipContents([Контент файла])),

#"Проверка целостности" = Table.AddColumn(#"Вызвана настраиваемая функция","IsEmpty", each Table.IsEmpty([fx_UnzipContents])),

#"Строки с примененным фильтром" = Table.SelectRows(#"Проверка целостности", each ([IsEmpty] = false)),

#"Развернутый элемент fx_UnzipContents" = Table.ExpandTableColumn(#"Строки с примененным фильтром", "fx_UnzipContents", {"FileName", "Content"}, {"FileName", "Content"}),

#"Исключение не xml" = Table.SelectRows(#"Развернутый элемент fx_UnzipContents", each (Text.End([FileName],4) = ".xml")),

#"Добавлен пользовательский объект" = Table.AddColumn(#"Исключение не xml", "Содержание XML", each Xml.Tables([Content])),

#"Развернутый элемент Содержание XML" = Table.ExpandTableColumn(#"Добавлен пользовательский объект", "Содержание XML", {"Name", "Table"}, {"Name", "Table"}),

#"Развернутый элемент Table" = Table.ExpandTableColumn(#"Развернутый элемент Содержание XML", "Table", {"http://zakupki.gov.ru/oos/types/1", "Attribute:schemeVersion"}, {"http://zakupki.gov.ru/oos/types/1", "Attribute:schemeVersion"}),

#"Другие удаленные столбцы1" = Table.SelectColumns(#"Развернутый элемент Table",{"http://zakupki.gov.ru/oos/types/1"}),

#"Развернутый элемент http://zakupki.gov.ru/oos/types/1" = Table.ExpandTableColumn(#"Другие удаленные столбцы1", "http://zakupki.gov.ru/oos/types/1", {"id", "regNum", "number", "publishDate", "signDate", "versionNumber", "foundation", "customer", "protocolDate", "documentBase", "price", "currency", "singleCustomerReason", "executionDate", "finances", "products", "suppliers", "href", "printForm", "scanDocuments", "currentContractStage"}, {"id", "regNum", "number", "publishDate", "signDate", "versionNumber", "foundation", "customer", "protocolDate", "documentBase", "price", "currency", "singleCustomerReason", "executionDate", "finances", "products", "suppliers", "href", "printForm", "scanDocuments", "currentContractStage"}),

#"Развернутый элемент customer" = Table.ExpandTableColumn(#"Развернутый элемент http://zakupki.gov.ru/oos/types/1", "customer", {"regNum", "fullName", "inn", "kpp"}, {"customer.regNum", "customer.fullName", "customer.inn", "customer.kpp"}),

#"Развернутый элемент currency" = Table.ExpandTableColumn(#"Развернутый элемент customer", "currency", {"code", "name"}, {"currency.code", "currency.name"}),

#"Развернутый элемент executionDate" = Table.ExpandTableColumn(#"Развернутый элемент currency", "executionDate", {"month", "year"}, {"executionDate.month", "executionDate.year"}),

#"Развернутый элемент singleCustomerReason" = Table.ExpandTableColumn(#"Развернутый элемент executionDate", "singleCustomerReason", {"id", "name"}, {"singleCustomerReason.id", "singleCustomerReason.name"}),

#"Удаленные столбцы" = Table.RemoveColumns(#"Развернутый элемент singleCustomerReason",{"printForm", "scanDocuments"}),

#"Развернутый элемент foundation" = Table.ExpandTableColumn(#"Удаленные столбцы", "foundation", {"oosOrder"}, {"foundation.oosOrder"}),

#"Развернутый элемент foundation.oosOrder" = Table.ExpandTableColumn(#"Развернутый элемент foundation", "foundation.oosOrder", {"notificationNumber", "lotNumber", "placing"}, {"foundation.oosOrder.notificationNumber", "foundation.oosOrder.lotNumber", "foundation.oosOrder.placing"}),

#"Развернутый элемент suppliers" = Table.ExpandTableColumn(#"Развернутый элемент foundation.oosOrder", "suppliers", {"supplier"}, {"suppliers.supplier"}),

#"Развернутый элемент suppliers.supplier" = Table.ExpandTableColumn(#"Развернутый элемент suppliers", "suppliers.supplier", {"participantType", "inn", "kpp", "organizationName", "country", "factualAddress", "postAddress", "contactPhone"}, {"suppliers.supplier.participantType", "suppliers.supplier.inn", "suppliers.supplier.kpp", "suppliers.supplier.organizationName", "suppliers.supplier.country", "suppliers.supplier.factualAddress", "suppliers.supplier.postAddress", "suppliers.supplier.contactPhone"}),

#"Развернутый элемент suppliers.supplier.country" = Table.ExpandTableColumn(#"Развернутый элемент suppliers.supplier", "suppliers.supplier.country", {"countryCode", "countryFullName"}, {"suppliers.supplier.country.countryCode", "suppliers.supplier.country.countryFullName"}),

#"Развернутый элемент finances" = Table.ExpandTableColumn(#"Развернутый элемент suppliers.supplier.country", "finances", {"financeSource", "extrabudget", "extrabudgetary"}, {"finances.financeSource", "finances.extrabudget", "finances.extrabudgetary"}),

#"Развернутый элемент finances.extrabudget" = Table.ExpandTableColumn(#"Развернутый элемент finances", "finances.extrabudget", {"code", "name"}, {"finances.extrabudget.code", "finances.extrabudget.name"}),

#"Развернутый элемент finances.extrabudgetary" = Table.ExpandTableColumn(#"Развернутый элемент finances.extrabudget", "finances.extrabudgetary", {"month", "year", "substageMonth", "substageYear", "KOSGU", "price"}, {"finances.extrabudgetary.month", "finances.extrabudgetary.year", "finances.extrabudgetary.substageMonth", "finances.extrabudgetary.substageYear", "finances.extrabudgetary.KOSGU", "finances.extrabudgetary.price"}),

#"Развернутый элемент products" = Table.ExpandTableColumn(#"Развернутый элемент finances.extrabudgetary", "products", {"product"}, {"products.product"}),

#"Развернутый элемент products.product" = Table.ExpandTableColumn(#"Развернутый элемент products", "products.product", {"sid", "OKPD", "name", "OKEI", "price", "quantity", "sum"}, {"products.product.sid", "products.product.OKPD", "products.product.name", "products.product.OKEI", "products.product.price", "products.product.quantity", "products.product.sum"}),

#"Развернутый элемент products.product.OKPD" = Table.ExpandTableColumn(#"Развернутый элемент products.product", "products.product.OKPD", {"code", "name"}, {"products.product.OKPD.code", "products.product.OKPD.name"}),

#"Развернутый элемент products.product.OKEI" = Table.ExpandTableColumn(#"Развернутый элемент products.product.OKPD", "products.product.OKEI", {"code", "nationalCode"}, {"products.product.OKEI.code", "products.product.OKEI.nationalCode"})

in

#"Развернутый элемент products.product.OKEI"


А это на случай, если захотите посмотреть мой файлик.

MS, Libreoffice & Google docs

762 поста14.9K подписчика

Правила сообщества

1. Не нарушать правила Пикабу

2. Публиковать посты соответствующие тематике сообщества

3. Проявлять уважение к пользователям

4. Не допускается публикация постов с вопросами, ответы на которые легко найти с помощью любого поискового сайта.

По интересующим вопросам можно обратиться к автору поста схожей тематики, либо к пользователям в комментариях


Важно - сообщество призвано помочь, а не постебаться над постами авторов! Помните, не все обладают 100 процентными знаниями и навыками работы с Office. Хотя вы и можете написать, что вы знали об описываемом приёме раньше, пост неинтересный и т.п. и т.д., просьба воздержаться от подобных комментариев, вместо этого предложите способ лучше, либо дополните его своей полезной информацией и вам будут благодарны пользователи.

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

Автор поста оценил этот комментарий

А что на профильных ресурсах забанили?

раскрыть ветку (1)
2
Автор поста оценил этот комментарий

Нет, просто здесь охват шире...и сообщество тоже соответствующее.

10
Автор поста оценил этот комментарий

Тезисно:

- Если падают неведомые ошибки, то нужно их прочитать, понять и действовать в зависимости от ошибки

- 20 ГБ - это даже не рядом с BigData. BigData - это когда хотя бы терабайт.

- Никто в здравом уме не работает в памяти с XML (или JSON) такого объёма. Это транспортный формат. Первое, что нужно сделать - это залить его в базу, например в реляционную. Делать это нужно не в памяти, а поточной трансформацией через какой-нибудь SAX или готовым приложением, которое такое умеет.

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

Спасибо за совет, буду пробовать

3
Автор поста оценил этот комментарий

Не совсем понял в деталях задумку, ну да ладно. Загрузка с фтп крашить не может, там в оперативку идёт маленькими кусочками и сразу ложится на диск, распаковка архива работает также кусочками. Остаётся обработка xml файла. Судя по всему, как раз тут сие творенье и пытается сразу делать все в оперативке. Так нельзя. Можно кодом на c# (кажется класс называется xml reader, тоже читает кусочками) загнать в любую БД, скажем mssql dev. Edition (бесплатный). И из неё powerbi, как уже из родной бд все построит. И вот все подобное счастье строится как правило в ssis - проекте.

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

Отличный совет, почитаю, спасибо.

0
Автор поста оценил этот комментарий

прикольно... вы с фэтэпэ же ресурса данные забираете? винцп - самое то для этого. штатный виндовый ftp-клиент же для этого никак (особенно, если с ключиком -s).

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

А я не умею(( Отментори меня плиз! Что и как предлагаешь?

показать ответы
0
Автор поста оценил этот комментарий

а разве wincp - штатное? впрочем, если работает, то не заморачивайтесь.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий
Я был бы очень благодарен за пример в вашем стиле... если потратите время и покажете , было бы чудесно.
показать ответы
0
Автор поста оценил этот комментарий

если про "штатный" ftp - так там уметь нечего. в cmd (или win-r) запускаешь ftp. вводите команды, которые у вас в скрипте для вин-цп.  убеждаетесь, что все ок. сохраняете в текст. потом в батнике "ftp -s:ваш_ваш_файл". должно взлететь.

с павершел тоже просто: https://www.google.com/search?q=powershell%20ftp%20request

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

хм...хм....  а чём тогда разница с моим решением, не понял... у меня вроде как тоже штатными средствами всё, нет? (тут я поплыл, не разбираюсь сильно)

показать ответы
0
DELETED
Автор поста оценил этот комментарий

Если там данные в формате xml и файлы большие - вам никакой оперативки не хватит с ними работать! Нужно трансформировать их в что-то плоское, типа csv. Делать это нужно при помощи xslt.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Понял, почитаю. Спасибо.

0
Автор поста оценил этот комментарий
Чтоб с батниками не пердолиться, можно использовать rclone, sync2go
раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Пожалуйста, расскажи подробней! Я не знаю что это! Научи немного... плиз