# Парсер логов касс ## Основная информация Это инструкция к `Pyaterochka log parser v.0.1.0` Парсер состоит из двух файлов: * `parser.py` - сам код парсера, * `config.yml` - конфигурационный файл. Перед запуском парсера, нужно установить Python версиии 3.7. Все недостающие модули парсер докачает сам при первом запуске. ## Конфигурационный файл (`config.yml`) Здесь задаются все основные настройки парсера, откуда читать логи, как они называются, сколько файлов читать за раз и так далее, сейчас об этом поподробнее. * `data_folder` - путь до папки с логами магазина * `pos_folder` - общая часть названия папок с логами касс (если указано `pos`, значит папки называются `pos*`, где `*` это произвольные символы) * `log_file_names` - общая часть названия файлов с логами (принцип работы такой же как и у `pos_folder`) * `res_folder` - путь до папки в которую сохранять результаты парсинга * `temp_folder` - путь до папки в которую сохранять временные файлы (желательно эту папку удалить после работы) * `file_from` - с какого файла начинать парсинг (номер файла, не название) * `file_to` - до какого файла парсить (если ничего не указано, парсить все файлы) * `files_step` - сколько файлов читать за один раз * `num_of_workers` - сколько паралельных процессов запускать (выбор зависит от количества ядер процессора) * `min_time_delta` - минимальное количество времени между сохраняемыми файлами в часах (не ставить меньше 1, так как файлы могут перезаписаться следующими) * `language` - язык на котором парсер будет писать в консоль Вот пример конфигурации: ```yaml= settings: data_folder: data/O186/ log_file_names: std_pos.log- pos_folder: pos res_folder: res/O186/ temp_folder: temp/O186/ file_from: 0 file_to: files_step: 15 num_of_workers: 4 min_time_delta: 1 language: eng ``` Получается, с данной конфигурацией парсер будет читать из папок: ``` /data/O136/pos1/std_pos.log-0000000 std_pos.log-0100000 ... pos2/std_pos.log-0000000 std_pos.log-0100000 ... ... ``` И писать в папку: ``` /res/O186/pos1/merged_logs.json ... pos2/merged_logs.json ... ... ``` ## Запуск парсера После скачивания нужной версии Python'а и настройки конфигурационного файла можно приступить к запуску парсера, для этого можно просто открыть командную строку в папке с парсером и написать команду `python parser.py` и парсер начнёт свою работу. Так же у парсера есть пара флагов, которые можно передать при запуске через командную строку: * `--pos_num` - логи какой кассы парсить (если ничего не передавать, парсятся логи со всех касс) * `--merge_results` - при передаче этого флага, результаты парсинга объединятся в общий файл по кассе * `--parse_purchases` - парсить ли данные о покупках (запускать только после того, как был выполнен `merge_results`) * `--skip_parsing_files` - пропустить парсинг файлов (если он уже был выполнен) * `--delete_temp_files` - удалить после работы парсера временные файлы ## Результаты работы После запуска программы могут получиться следующие типы файлов: * `merged_logs.json` - файл со всеми распарсенными логами этой кассы * `merged_purchases.json` - файл со всеми операциями связанными с покупками на этой кассе * `merged_items.json` - файл со всеми купленными товарами на этой кассе (грязный, содержит повторяющуюся информацию) * `merged_returns.json` - файл со всеми возвращёнными товарами * `purchases_clean.p` - файл с очищенными данными о покупках (все файлы в формате `.p`, это pickle файлы для распаковки в питоне, в них содержится pandas Dataframe с соответствующими данными) * `items_clean.p` - файл с очищенным списком купленных товаров ## Примеры результатов: ### `merged_logs.json` ```json {"time": "2019-02-19 07:35:44.808000", "parsed_type": "bank_payment_end", "parsed_data": null} {"time": "2019-02-19 07:35:44.850000", "parsed_type": "issurance_or_return_end", "parsed_data": {"id": "22759520"}} {"time": "2019-02-19 07:35:47.005000", "parsed_type": "authorization_start", "parsed_data": null} {"time": "2019-02-19 07:37:00.833000", "parsed_type": "check_formation_end", "parsed_data": null} {"time": "2019-02-19 07:37:23.498000", "parsed_type": "cash_receipt_end_and_drawer_close", "parsed_data": null} {"time": "2019-02-19 07:38:00.053000", "parsed_type": "check_cashier_id", "parsed_data": {"pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир"}} {"time": "2019-02-19 07:38:04.385000", "parsed_type": "check_end_print", "parsed_data": null} {"time": "2019-02-19 07:38:05.184000", "parsed_type": "check_formation_end", "parsed_data": null} {"time": "2019-02-19 07:38:05.861000", "parsed_type": "plu_search_start", "parsed_data": {"ean": "0", "art_nr": "null"}} {"time": "2019-02-19 07:38:05.865000", "parsed_type": "plu_search_end", "parsed_data": {"elapsed_time": "4"}} {"time": "2019-02-19 07:38:06.150000", "parsed_type": "authorization_status", "parsed_data": {"status": "OK", "login_bon_id": "E161001000000000000000000952019021907:37"}} {"time": "2019-02-19 07:38:06.159000", "parsed_type": "barcode_item3", "parsed_data": null} {"time": "2019-02-19 07:38:06.375000", "parsed_type": "operation_end", "parsed_data": {"id": "12300276"}} {"time": "2019-02-19 07:43:06.485000", "parsed_type": "check_formation_end", "parsed_data": null} ``` ### `merged_items.json` ```json {"time": "2019-02-19 09:16:19.556000", "id": 3602487, "i_name": "СИГАРЕТЫ ROTHMANS ДЕМИ КЛИК ПАЧ", "quantity": 1.0, "vat_info": "1", "unit_price": 105.0, "price": 105.0, "unit_name": "ST", "pre_text": "", "post_text": "", "receipt_id": 1, "sub_id": 0} {"time": "2019-02-19 09:17:11.564000", "receipt_id": 2, "sub_id": 0, "id": 3300573, "groupcode": "1", "quantity": 1.0, "price": 5.0} {"time": "2019-02-19 09:17:11.564000", "receipt_id": 2, "sub_id": 0, "id": 3296712, "groupcode": "1", "quantity": 1.0, "price": 64.99} {"time": "2019-02-19 09:17:11.564000", "receipt_id": 2, "sub_id": 0, "id": 3306904, "groupcode": "1", "quantity": 1.0, "price": 69.99} {"time": "2019-02-19 09:17:11.564000", "receipt_id": 2, "sub_id": 0, "id": 3337159, "groupcode": "1", "quantity": 1.0, "price": 54.99} {"time": "2019-02-19 09:17:35.435000", "receipt_id": 2, "sub_id": 2, "id": 3300573, "groupcode": "0", "quantity": 1.0, "price": 5.0} {"time": "2019-02-19 09:17:35.435000", "receipt_id": 2, "sub_id": 2, "id": 3296712, "groupcode": "0", "quantity": 1.0, "price": 64.99} {"time": "2019-02-19 09:17:35.435000", "receipt_id": 2, "sub_id": 2, "id": 3306904, "groupcode": "0", "quantity": 1.0, "price": 69.99} {"time": "2019-02-19 09:17:35.435000", "receipt_id": 2, "sub_id": 2, "id": 3337159, "groupcode": "0", "quantity": 1.0, "price": 54.99} {"time": "2019-02-19 09:17:40.592000", "id": 3300573, "i_name": "Пакет ПЯТЕРОЧКА 65х40см", "quantity": 1.0, "vat_info": "1", "unit_price": 5.0, "price": 5.0, "unit_name": "ST", "pre_text": "", "post_text": "", "receipt_id": 2, "sub_id": 4} {"time": "2019-02-19 09:17:40.674000", "id": 3296712, "i_name": "РЯЗАН.Мука ПШЕНИЧ.ЭКСТРА 2кг", "quantity": 1.0, "vat_info": "2", "unit_price": 64.99, "price": 64.99, "unit_name": "ST", "pre_text": "", "post_text": "", "receipt_id": 2, "sub_id": 4} {"time": "2019-02-19 09:17:40.683000", "id": 3306904, "i_name": "МААГ Кишмиш светлый 250г", "quantity": 1.0, "vat_info": "1", "unit_price": 69.99, "price": 69.99, "unit_name": "ST", "pre_text": "", "post_text": "", "receipt_id": 2, "sub_id": 4} {"time": "2019-02-19 09:17:40.689000", "id": 3337159, "i_name": "BAR.Макар.ДЖИРАНДОЛЕ 500г", "quantity": 1.0, "vat_info": "2", "unit_price": 54.99, "price": 54.99, "unit_name": "ST", "pre_text": "", "post_text": "", "receipt_id": 2, "sub_id": 4} ``` ### `merged_purchases.json` ```json {"time": "2019-02-19 09:16:22.026000", "store_id": "E161", "type": "check", "r_id": 1, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 0, "num_of_items": 1, "receipt_id": -1} {"type": "lrequest", "time": "2019-02-19 09:17:11.564000", "receipt_id": 109065, "r_id": 2, "sub_id": 0, "lcard_num": "7789000097893459", "amount": 194.97, "amount_pbp": null, "num_of_items": 4, "store_id": "E161"} {"time": "2019-02-19 09:17:17.167000", "type": "lresponse", "r_id": 2, "sub_id": 1, "lname": null, "ladded_points": 104, "lpromo_points": 0, "ltotal": 104, "error_code": 0} {"type": "lrequest", "time": "2019-02-19 09:17:35.435000", "receipt_id": 109065, "r_id": 2, "sub_id": 2, "lcard_num": "7789000097893459", "amount": 194.97, "amount_pbp": 1.0, "num_of_items": 4, "store_id": "E161"} {"time": "2019-02-19 09:17:35.989000", "type": "lresponse", "r_id": 2, "sub_id": 3, "lname": "мария", "ladded_points": 9, "lpromo_points": 0, "ltotal": 113, "error_code": 0} {"time": "2019-02-19 09:17:45.890000", "store_id": "E161", "type": "check", "r_id": 2, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 4, "card_type": "MIR Premium DBT", "card_num": "************3147", "card_name": "DEMENKOVA MARIYA", "amount": 194.97, "num_of_items": 4, "receipt_id": -1} {"time": "2019-02-19 09:18:18.814000", "store_id": "E161", "type": "check", "r_id": 3, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 0, "num_of_items": 2, "receipt_id": -1} {"time": "2019-02-19 09:21:30.326000", "store_id": "E161", "type": "check", "r_id": 4, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 0, "card_type": "Visa", "card_num": "************0983", "card_name": null, "amount": 264.2, "num_of_items": 3, "receipt_id": -1} {"time": "2019-02-19 09:26:07.165000", "store_id": "E161", "type": "check", "r_id": 5, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 0, "num_of_items": 1, "receipt_id": -1} {"time": "2019-02-19 09:30:29.046000", "store_id": "E161", "type": "check", "r_id": 6, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 0, "card_type": "MASTERCARD", "card_num": "************9718", "card_name": "BATURIN LEV", "amount": 88.0, "num_of_items": 1, "receipt_id": -1} {"time": "2019-02-19 09:37:42.234000", "store_id": "E161", "type": "check", "r_id": 7, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 0, "card_type": "Visa", "card_num": "************6231", "card_name": null, "amount": 45.99, "num_of_items": 1, "receipt_id": -1} {"time": "2019-02-19 09:38:02.517000", "store_id": "E161", "type": "check", "r_id": 8, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 0, "card_type": "Mastercard", "card_num": "************3050", "card_name": null, "amount": 95.0, "num_of_items": 1, "receipt_id": -1} {"time": "2019-02-19 09:56:00.184000", "store_id": "E161", "type": "check", "r_id": 9, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 0, "num_of_items": 3, "receipt_id": -1} {"type": "lrequest", "time": "2019-02-19 09:58:53.575000", "receipt_id": 109073, "r_id": 10, "sub_id": 0, "lcard_num": "7789004690698281", "amount": 479.0, "amount_pbp": 1.0, "num_of_items": 5, "store_id": "E161"} {"time": "2019-02-19 09:58:54.500000", "type": "lresponse", "r_id": 10, "sub_id": 1, "lname": "\u0435\u043b\u0435\u043d\u0430", "ladded_points": 23, "lpromo_points": 0, "ltotal": 937, "error_code": 0} {"time": "2019-02-19 09:59:03.570000", "store_id": "E161", "type": "check", "r_id": 10, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 2, "num_of_items": 6, "receipt_id": -1} {"time": "2019-02-19 10:01:12.964000", "store_id": "E161", "type": "check", "r_id": 11, "pos_id": "1", "cashier_name": "Васильева Валерия Александровна", "cashier_type": "Продавец-кассир", "sub_id": 0, "card_type": "Visa", "card_num": "************0738", "card_name": null, "amount": 45.1, "num_of_items": 1, "receipt_id": -1} ``` ### `clean_purchases.p` <table border="1" class="dataframe"> <thead> <tr style="text-align: right"> <th></th> <th>time</th> <th>init_amount</th> <th>final_amount</th> <th>lname</th> <th>lcard_num</th> <th>ladded_points</th> <th>lpromo_points</th> <th>ltotal</th> <th>card_name</th> <th>card_type</th> <th>card_num</th> <th>store_id</th> <th>pos_id</th> <th>cashier_name</th> <th>cashier_type</th> </tr> <tr> <th>receipt_id</th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> </tr> </thead> <tbody> <tr> <th>1</th> <td>2019-02-19 09:16:22.026</td> <td>105.00</td> <td>105.00</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>E161</td> <td>1</td> <td>Васильева Валерия Александровна</td> <td>Продавец-кассир</td> </tr> <tr> <th>2</th> <td>2019-02-19 09:17:45.890</td> <td>194.97</td> <td>194.97</td> <td>мария</td> <td>7789000097893459</td> <td>9.0</td> <td>0.0</td> <td>113.0</td> <td>DEMENKOVA MARIYA</td> <td>MIR Premium DBT</td> <td>************3147</td> <td>E161</td> <td>1</td> <td>Васильева Валерия Александровна</td> <td>Продавец-кассир</td> </tr> <tr> <th>3</th> <td>2019-02-19 09:18:18.814</td> <td>148.99</td> <td>148.00</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>NaN</td> <td>E161</td> <td>1</td> <td>Васильева Валерия Александровна</td> <td>Продавец-кассир</td> </tr> </tbody> </table> ### `clean_items.p` <table border="1" class="dataframe"> <thead> <tr style="text-align: right"> <th></th> <th>id</th> <th>price</th> <th>quantity</th> </tr> <tr> <th>receipt_id</th> <th></th> <th></th> <th></th> </tr> </thead> <tbody> <tr> <th>1</th> <td>3602487</td> <td>105.00</td> <td>1.0</td> </tr> <tr> <th>2</th> <td>3300573</td> <td>5.00</td> <td>1.0</td> </tr> <tr> <th>2</th> <td>3296712</td> <td>64.99</td> <td>1.0</td> </tr> <tr> <th>2</th> <td>3306904</td> <td>69.99</td> <td>1.0</td> </tr> <tr> <th>2</th> <td>3337159</td> <td>54.99</td> <td>1.0</td> </tr> <tr> <th>3</th> <td>3628404</td> <td>37.99</td> <td>1.0</td> </tr> <tr> <th>3</th> <td>3674398</td> <td>111.00</td> <td>1.0</td> </tr> <tr> <th>4</th> <td>41930</td> <td>97.80</td> <td>1.0</td> </tr> <tr> <th>4</th> <td>3639576</td> <td>51.40</td> <td>1.0</td> </tr> <tr> <th>4</th> <td>3356406</td> <td>115.00</td> <td>1.0</td> </tr> </tbody> </table>