Сегодня в платформу Diggernaut была добавлена поддержка файлов в формате XLS, XLSX и CSV. Схема поддержки реализована в том же формате как и у других поддерживаемых типов файлов. Вы загружаете в диггер файл, используя команду walk, диггер получает файл, определяет его тип и конвертирует его в XML. Далее вы можете ходить по DOM структуре, извлекать нужные данные и формировать свой набор данных.
Рассмотрим на примере, как это работает. Для этого мы поместили 3 файла в нашу песочницу:
https://www.diggernaut.com/sandbox/sample.csv — CSV файл с данными
https://www.diggernaut.com/sandbox/sample.xls — XLS файл с данными (бинарная версия)
https://www.diggernaut.com/sandbox/sample.xlsx — XLSX файл с данными (XML версия)
Напишем очень простую конфигурацию диггера, которая будет забирать файл и в режиме отладки показывать нам исходный код конвертированных данных.
---
config:
debug: 2
agent: Firefox
do:
- walk:
to: https://www.diggernaut.com/sandbox/sample.csv
do:
Если мы запустим диггер в режиме отладки, то в логе мы увидим следующий исходный код XML страницы с данными
<html>
<head></head>
<body>
<doc>
<sheet name="default">
<row class="1">
<column class="1">First</column>
<column class="2">Last</column>
<column class="3">Pcode</column>
<column class="4">Political Party</column>
</row>
<row class="2">
<column class="1">Smith</column>
<column class="2">Fred</column>
<column class="3">A</column>
<column class="4">Democratic</column>
</row>
<row class="3">
<column class="1">Robbins</column>
<column class="2">Terry</column>
<column class="3">1</column>
<column class="4">Green</column>
</row>
<row class="4">
<column class="1">O'Neill</column>
<column class="2">Susan</column>
<column class="3">B</column>
<column class="4">Republican</column>
</row>
<row class="5">
<column class="1">Parker</column>
<column class="2">Scott</column>
<column class="3">D</column>
<column class="4">American Independent</column>
</row>
<row class="6">
<column class="1">Perkins</column>
<column class="2">Ralph</column>
<column class="3">D</column>
<column class="4">American Independent</column>
</row>
<row class="7">
<column class="1">Talbot</column>
<column class="2">Angie</column>
<column class="3">7</column>
<column class="4">Middle Class Pty</column>
</row>
</sheet>
</doc>
</body>
</html>
Так как в CSV только один лист, то элемент sheet в результирующей структуре только один. В XLS/XLSX файлах листов может быть много, и все они будут находиться в соответсвующих элементах sheet. Парсить такую структуру достаточно легко, проходим по листам, затем по строкам row и забираем данные из колонок column. Значения в классах соответствуют номеру строк и столбцов в оригинальном файле.
Давайте теперь посмотрим, как будет сконвертирован XLS ресурс:
---
config:
debug: 2
agent: Firefox
do:
- walk:
to: https://www.diggernaut.com/sandbox/sample.xls
do:
Получим следующий исходный код:
<html>
<head></head>
<body>
<doc>
<sheet name="Voters">
<row class="1">
<column class="1">First</column>
<column class="2">Last</column>
<column class="3">Pcode</column>
<column class="4">Political Party</column>
</row>
<row class="2">
<column class="1">Smith</column>
<column class="2">Fred</column>
<column class="3">A</column>
</row>
<row class="3">
<column class="1">Robbins</column>
<column class="2">Terry</column>
<column class="3">1</column>
</row>
<row class="4">
<column class="1">O'Neill</column>
<column class="2">Susan</column>
<column class="3">B</column>
</row>
<row class="5">
<column class="1">Parker</column>
<column class="2">Scott</column>
<column class="3">D</column>
</row>
<row class="6">
<column class="1">Perkins</column>
<column class="2">Ralph</column>
<column class="3">D</column>
</row>
<row class="7">
<column class="1">Talbot</column>
<column class="2">Angie</column>
<column class="3">7</column>
</row>
</sheet>
<sheet name="Party Codes">
<row class="1">
<column class="1">PARTY CODE</column>
<column class="2">NAME</column>
</row>
<row class="2">
<column class="1">1</column>
<column class="2">Green</column>
</row>
<row class="3">
<column class="1">2</column>
<column class="2">Reform</column>
</row>
<row class="4">
<column class="1">3</column>
<column class="2">Whig</column>
</row>
<row class="5">
<column class="1">4</column>
<column class="2">Islamic Political Party of America</column>
</row>
<row class="6">
<column class="1">5</column>
<column class="2">Rock & Roll</column>
</row>
<row class="7">
<column class="1">6</column>
<column class="2">Natural Law</column>
</row>
<row class="8">
<column class="1">7</column>
<column class="2">Middle Class Pty</column>
</row>
<row class="9">
<column class="1">8</column>
<column class="2">Humanist</column>
</row>
<row class="10">
<column class="1">9</column>
<column class="2">Pragmatic</column>
</row>
<row class="11">
<column class="1">10</column>
<column class="2">Conscious American African Party</column>
</row>
<row class="12">
<column class="1">11</column>
<column class="2">Parliament Party</column>
</row>
<row class="13">
<column class="1">12</column>
<column class="2">United Conscious Builders of the Dream Party</column>
</row>
<row class="14">
<column class="1">13</column>
<column class="2">The Egalitarian Party</column>
</row>
<row class="15">
<column class="1">14</column>
<column class="2">The Humanitarian Party</column>
</row>
<row class="16">
<column class="1">15</column>
<column class="2">Scientifically Evolving University Party</column>
</row>
<row class="17">
<column class="1">16</column>
<column class="2">God, Truth & Love Party</column>
</row>
<row class="18">
<column class="1">17</column>
<column class="2">Superhappy Party</column>
</row>
<row class="19">
<column class="1">18</column>
<column class="2">Working Families Party</column>
</row>
<row class="20">
<column class="1">A</column>
<column class="2">Democratic</column>
</row>
<row class="21">
<column class="1">B</column>
<column class="2">Republican</column>
</row>
<row class="22">
<column class="1">C</column>
<column class="2">Decline to State</column>
</row>
<row class="23">
<column class="1">D</column>
<column class="2">American Independent</column>
</row>
<row class="24">
<column class="1">E</column>
<column class="2">Citizen Party</column>
</row>
<row class="25">
<column class="1">F</column>
<column class="2">Communist</column>
</row>
<row class="26">
<column class="1">G</column>
<column class="2">Conservative</column>
</row>
<row class="27">
<column class="1">H</column>
<column class="2">Environmentalist</column>
</row>
<row class="28">
<column class="1">I</column>
<column class="2">Ind. Progressive</column>
</row>
<row class="29">
<column class="1">J</column>
<column class="2">Liberal</column>
</row>
<row class="30">
<column class="1">K</column>
<column class="2">Peace & Freedom</column>
</row>
<row class="31">
<column class="1">L</column>
<column class="2">Prohibition</column>
</row>
<row class="32">
<column class="1">M</column>
<column class="2">New Economy</column>
</row>
<row class="33">
<column class="1">N</column>
<column class="2">Socialist</column>
</row>
<row class="34">
<column class="1">O</column>
<column class="2">Socialist Labor</column>
</row>
<row class="35">
<column class="1">P</column>
<column class="2">Pot Party</column>
</row>
<row class="36">
<column class="1">Q</column>
<column class="2">Libertarian</column>
</row>
<row class="37">
<column class="1">R</column>
<column class="2">Amer. Natl. Socialist</column>
</row>
<row class="38">
<column class="1">S</column>
<column class="2">Poor People’s Party</column>
</row>
<row class="39">
<column class="1">T</column>
<column class="2">Free</column>
</row>
<row class="40">
<column class="1">U</column>
<column class="2">National</column>
</row>
<row class="41">
<column class="1">V</column>
<column class="2">Constitution Party</column>
</row>
<row class="42">
<column class="1">W</column>
<column class="2">Vision</column>
</row>
<row class="43">
<column class="1">X</column>
<column class="2">Puritan</column>
</row>
<row class="44">
<column class="1">Y</column>
<column class="2">Federal</column>
</row>
<row class="45">
<column class="1">Z</column>
<column class="2">Misc.</column>
</row>
<row class="46">
<column class="1"></column>
<column class="2"></column>
</row>
</sheet>
</doc>
</body>
</html>
Как вы видите, в этом файле мы имеем 2 листа, а в остальном принципиально такую же структуру как и в случае с CSV. Если мы загрузим XLSX, то получим точно такой же результат как и с XLS, поэтому мы опустим этот момент.
Как можно использовать этот функционал, кроме собственно парсинга финальных данных? Как вариант, вы можете использовать таблицы как фид с ресурсами, которые должен забрать ваш парсер. К примеру, вы добавляете список ссылок на товары в магазине в таблицу. Ваш парсер читает таблицу, забирает список URL, кладет их в пул и затем начинает работу основная логика парсера по сбору данных о товарах. Или, представьте, что у вас есть таблица с данными, которые надо дополнить с веба, вы читаете парсером таблицу, проходите строку за строкой и формируете новый датасет, попутно заходя на страницы, скажем, товаров и дополняя данные о товаре. В результирующем датасете у вас будут данные из таблицы и со страницы товара, сведенные в единую запись. Если и другие варианты использования таблиц, но об этом в следующий раз.