NewTechAudit
169

Введение в парсинг или первый опыт анализа нетабличных данных

В закладки

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

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

Для специалиста не составляет труда провести анализ того или иного массива информации, открыв его в табличном редакторе либо сформировав прямой запрос в БД по условиям выборки. Но на практике, аналитики данных нередко встречают задачи по структурированию нетабличных текстовых данных, в т.ч. имеющих их табличное отображение, основанное на коде разметки веб-страниц, но не являющимися таблицами в полном смысле этого слова (html, htm и т.п.). Именно с таким видом представления некоторых ежедневных форм нетабличных отчетных данных мы столкнулись в своей работе. О том как мы решили подобную задачу, параллельно знакомясь с технологией парсинга, расскажем в этой статье.

Для начала предлагаем разобраться в объекте исследования — веб странице и ее коде разметки.

Рассмотрим пример таблицы в формате html:

​Отчет по платежам

Код гипертекстовой разметки данной таблицы будет выглядеть так:

<!DOCTYPE html> <html> <head> <title>Отчет по платежам</title> </head> <body> <p style="text-align: center;">Отчет по платежам</p> <table> <tbody> <tr> <td>Номер операции</td> <td>Дата</td> <td>ФИО</td> <td>Сумма</td> <td>Контрагент</td> <td>Комментарии</td> </tr> <tr> <td>1</td> <td>11.02.2019</td> <td>Иванов И.А.</td> <td>1233,15</td> <td>ООО Ромашка</td> <td>за лепесток</td> </tr> <tr> <td>2</td> <td>11.02.2019</td> <td>Степанов А.О.</td> <td>15000,00</td> <td>ЗАО Котелок</td> <td>за дрова</td> </tr> <tr> <td>3</td> <td>13.02.2019</td> <td>Лебедева А.Ш.</td> <td>7500,50</td> <td>ООО Ромашка</td> <td>&nbsp;</td> </tr> <tr> <td>4</td> <td>17.03.2019</td> <td>Вавилов Н.З.</td> <td>13,44</td> <td>ПАО Связьтранскопыта</td> <td>возврат</td> </tr> </tbody> </table> </body> </html>

Из кода видно, что за структуру таблицы в HTML отвечают так называемые тэги:

  • <table></table> - ограничивающие собой саму таблицу;

  • <tr></tr> - ограничивающие собой строки таблицы

  • <td></td> - ограничивающие собой ячейки строк

Теперь перед нами возникает задача: как привести этот закодированный текст в удобный нам табличный вид? И как это сделать если таких файлов формируется десятки (сотни) в день, а анализировать нам надо месяцы (или даже годы)? Здесь нам на помощь приходит Python и его модуль парсера “BS4 (beautifulsoup4)”.

Для успешного решения этой задачи нам потребуется передать для анализа в модуль BS4 Python таблицу ограниченную тегами <table>, предварительно внедрив в код сам модуль:

from bs4 import BeautifulSoup import csv # модуль для итогового экспорта данных в csv формат

Сначала следует часть типового решения Python по работе с файлом: интересующий нас файл открывается Python, “зачитывается” полностью в переменную и передается модулю bs4.

filename = # путь до файла infile = io.open(filename, ‘r’) # открывается файл в режиме чтения data = infile.read() # “чтение” данных из файла в переменную infile.close() # закрытие файла soup = BeautifulSoup(‘’.join(data), ‘lxml’) # преобразование данных файла в формат BS4 с учетом предустановок ‘lxml’, ‘html’ и т.п. и передача их в переменную soup

Следующим этапом следует определение самой таблицы в общей массе кода по тегу <Table> и сведение всех ячеек в один список.

rows = [ ] table_data = soup.find(‘table’) # находим массив данных ограниченных <table> for td in tabledata.find_all(‘td’): rows.append(td.text.strip()) # формируем список из значений каждой пары <td></td>, т.е. всех ячеек

Сформированный общий список значений всех ячеек нам надо вернуть по строкам

rows_upd = {} # создаем словарь, ключом которого будет номер строки, значение - список из значений ячеек первой строки i = 0 while len(rows) > 0: i += 1 rows_upd[i] = rows[:6] # формируем строки в словаре del rows[:6] # удаляем переданные в словарь строки из общей массы

Теперь полученный словарь с данными таблицы мы можем с уверенностью подвергнуть анализу как средствами самого Python так и экспортировать в файл, например, в формат csv.

path = # путь к файлу экспорта формата csv with open(path, ‘a’, newline=’’) as csvfile: # открытие для записи файла csv writer = csv.writer(csvfile, delimiter=’;’) # определение формата файла, разделителя столбцов for key in rows_upd.keys(): writer.writerow(rows_upd[key]) # последовательная запись каждой строки словаря согласно ранее сформированного ключа

В конечном итоге мы получаем текстовый файл формата csv с разделителями, позволяющий нам экспортировать данные в любой табличный редактор или базу данных.

Указанный вариант реализации парсинга текстовых отчетов описан в упрощенном виде. Нами он успешно используется при импорте ежедневных текстовых отчетов за период путем дополнительной организации циклов поочередного чтения файлов самим модулем по настройкам вида и структуры отчетов.

{ "author_name": "NewTechAudit", "author_type": "editor", "tags": [], "comments": 0, "likes": 1, "favorites": 4, "is_advertisement": false, "subsite_label": "newtechaudit", "id": 109360, "is_wide": false, "is_ugc": false, "date": "Thu, 27 Feb 2020 10:47:21 +0300", "is_special": false }
Создать объявление на vc.ru
Право
Семь настоящих причин зарегистрировать товарный знак в России
Хорошее название помогает компании защититься от подделок, покорить рынок и выйти за рубеж. Плохое может её обанкротить.
0
Комментариев нет
Популярные
По порядку

Прямой эфир