Распознавание чеков в Google Docs с помощью ABBYY OCR SDK

  • Tutorial
В северном полушарии нынче зима, а это значит что пора на лыжи! Мы с друзьями поддались этому течению и приступили к подготовке нашего совместного зимнего отдыха. Детали всего процесса планирования раскрывать не буду, скажу лишь только, что мне выпала ответственная роль сбора магазинных чеков наших совместных трат.

Так как песочницей для наших планов выступили Google Docs, а конкретнее Таблицы, то мне захотелось разместить фото всех чеков на отдельном листе. Первая попытка вставить картинку в таблицу через привычный пункт меню «Вставка → Изображение» привела к тому что чек оказался поверх ячеек таблицы и моим друзьям IT-шникам такое оформление точно бы не приглянулось:



«Должен же быть способ вставить картинку в ячейку...», — подумал я. Google нашел этот способ с первого запроса: функция IMAGE(URL), как значение ячейки. Ну что ж, дело сделано:



Можно дальше идти смотреть лыжные уроки. Хотя…

...Google моментально среагировал на мой запрос «Online FineReader API» и выдал несколько статей с хабра о ABBYY Cloud OCR SDK. Быстрый просмотр доступных методов платформы подтвердил мои надежды и желанный ocrsdk.com/documentation/apireference/processReceipt был найден. Для осуществления задуманного недоставало понимания как вставить в ячейку таблицы пользовательскую функцию, которая будет вызывать методы обработки чека. Но и тут поиск меня не подвел и был найден Редактор скриптов Google.

Теперь дело за малым. Первым делом необходимо создать приложение ocrsdk. Делается это в процессе регистрации нового пользователя, так что с этим проблем не возникло. Письмо с паролем приложения, который необходим для аутентификации запросов, было отправлено сразу после завершения регистрации.

Далее в нашей Таблице выбираем пункт меню «Инструменты → Редактор скриптов» и создаем функцию processReceipt(imageUrl):

function processReceipt(imageUrl) {
    
    // Загружаем картинку чека
    var image =      UrlFetchApp.fetch(imageUrl);
  
    // Формируем заголовок авторизации, который состоит из имени приложения и пароля
    var pass = "GoogleDriveTest" + ":" + "********************"
    
    // Формируем POST запрос на обработку чека
    var url = "http://cloud.ocrsdk.com/processReceipt";
    var headers = {
        "Content-Type":"image/png",
        "Authorization" : "Basic " + Utilities.base64Encode(pass)
    };
    
    var options = {
        "method":"POST",
        "headers": headers,
        "payload" : image.getContent()
    };
    var response = UrlFetchApp.fetch(url, options);
    
  
    // Парсим XML ответа и находим в нем ID задачи по обработке нашего чека (больше деталей тут http://ocrsdk.com/documentation/apireference/processReceipt/)
    var document = XmlService.parse(response.getContentText())
    var id = document.getRootElement().getChildren()[0].getAttribute('id').getValue()
    
    var resultUrl
    
    // Ждем успешного завершения задачи и получаем url по которому можно получить результат обработки чека
    do {
        Utilities.sleep(3000)
        
        url = "http://cloud.ocrsdk.com/getTaskStatus" + "?taskId=" + id;
        headers = {
            "Authorization" : "Basic " + Utilities.base64Encode(pass)
        };
        
        options = {
            "method":"GET",
            "headers": headers,
        };
        
        response = UrlFetchApp.fetch(url, options);
        
        document = XmlService.parse(response.getContentText());
        if (document.getRootElement().getChildren()[0].getAttribute('status').getValue() == 'Completed') {
            resultUrl = document.getRootElement().getChildren()[0].getAttribute('resultUrl').getValue()
            break
        }
    } while(true)
        
    // Получаем результат обработки чека
    options = {
        "method":"GET",
    };
    
    response = UrlFetchApp.fetch(resultUrl, options);
    document = XmlService.parse(response.getContentText());
    
    // document содаржит XML нашего чека. Из-за моральных принципов реализацию функции findTotalPriceInReceiptXML я скрыл :)
    result = findTotalPriceInReceiptXML(document)
    
    return result
}

Всё сохраняем и идем обратно в таблицу. Чтоб сие чудо заработало, пришлось вынести в отдельную ячейку таблицы URL картинки чека. Наша функция теперь доступна как =processReceipt(ячейка с URL).



Всем хорошей зимней погоды и удачи на лыжных склонах!
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 43

    0
    After the registration Customer will automatically receive a Free Test Set through his account. This test set consists of Free 50 Customer’s A4 Images – any 50 images which are valid for 90 days after the registration has been completed.

    Receipt is considered to be an image processed with processReceipt method. Every Receipt recognition is charged as a recognition of two A4 pages.

    Т.е. лишь 25 чеков можно распознать бесплатно. Печально.
      +1
      Хотя можно 100 страниц в месяц получить бесплатно — http://blog.ocrsdk.com/get-the-best-ocr-technology-for-free. Уже лучше :).
        0

        Если нужно поставить на поток попробуйте tesseract, там есть поддержка большого количества языков. Он, конечно же менее комфортен, но с подобным чеком справиться без поблем.


        Недавно обновились натренированные модели для многих языков

        +3
        Что-то мне подсказывает, что просто вбить «134.36» руками было бы быстрее, чем фотографировать чек, вставлять его в документ и распознавать. Здесь нужно писать приложение для телефона, которое само фотографирует чек и распознаёт его.
          0
          Вы правы в том что приложение решит задачу организации базы фотографий чеков с их распознаванием более качественно. Более того, таких приложений написано предостаточно. А вот метод продемонстрированный в статье, хоть и не оптимален, но достаточно оригинален. Его плюс в том, что всё что вам надо сделать — написать логику по обработке изображения, а вот о визуальной составляющей уже позаботились инженеры google.
          0
          Проблема в том, что у каждого магазина свой чек и свой лейаут данных, часто с невообразимыми переносами. Буквально на днях решал такую же задачу — занесение данных с чеков в домашнюю бухгалтерию. Был написан бот в телеграме, который принимает потоком позиции расхода / прихода в виде «хлеб 123 еда» (товар, стоимость, категория), причем эти данные вносятся голосовым набором с мобильного устройства (распознавание идет средствами android / ios автоматически, распознанная команда отправляется как текст). Есть возможность посмотреть статистику за указанный год / месяц / день и выгрузить это все в виде csv, который уже потом можно залить в google docs и построить всевозможные графики. Жена говорит, что нравится и что стало гораздо удобнее заносить данные, чем вручную вбивать в таблицу.
            +1
            Да, проделанная в статье работе не более чем демонстрация возможностей указанных технологий. Для серьезного дела я бы не рассчитывал на данный вид анализа. Плюс, сервис был очень удивлен, увидев польский чек, скажу я Вам.
              +1
              То, что описал выше, выглядит примерно вот так:
              Длинный скриншот


              Все введено надиктовкой, без клавиатуры, либо выбором из быстрых команд. Если больше 1 позиции, то получается гораздо быстрее, чем руками.
              0
              О, а не дадите ссылку на бота?
                0
                Он «приватный», т.е. будет отбивать всех пользователей не из разрешенного списка. Возможно, когда подчищу говнокод — выложу в паблик. Но там все просто на самом деле — nodejs + node-telegram-bot-api. Если сильно надо, то пишите, отдам так.
              0
              Нужно оплачивать с карточки, тогда такое распознование не понадобится. :)

              p.s.А есть вообще на Android приложения которые фоткают и распознают чеки? Искал пару лет назад — не нашел. Но может что-то уже появилось или искал плохо?
                0
                1. Не везде есть возможность выгрузки из ЛК банка
                2. Не везде есть терминалы, часто требуют платить в кассу наличкой, например, на шиномонтаже в замкадье такое часто встречается.
                3. Возможно карточек больше одной и они от разных банков — см. пункт 1 :)

                Чеки являются универсальным носителем нужной информации, пусть и не унифицированной.
                  0
                  Много лет пользуюсь одним из сервисов для ведения домашней бухгалтерии.
                  1. ЛК банка не нужен. Всё работает через СМС информирование о операциях по картам, на смартфоне в фоне приложение которое распознает и отправляет на сервер всё операции.
                  2. Живу в 80км от дефолтсити, 93% всех расходов с банковских карт.
                  3. Карт у меня 7 штук от 4 разных банков, в разных валютах, всё работает без каких либо проблем.

                  Чеки не удобны для долгосрочного хранения, нужно много места и уже через пару лет на них сложно что то разобрать.
                    0
                    Чеки не удобны для долгосрочного хранения

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

                    Всё работает через СМС информирование о операциях по картам, на смартфоне в фоне приложение которое распознает и отправляет на сервер всё операции.

                    Так приходит только общая сумма, а хотелось бы разбивку по категориям. Практически всегда категорий больше чем одна. Это нужно для дальнейшего анализа, на что было сколько потрачено за определенный период, графики, все дела.

                    93% всех расходов с банковских карт

                    Примерно так же, apple pay принимается практически в 100% терминалов (сбербанк постарался — обновил практически все терминалы), но все-равно приходится с собой таскать 2-3к наличкой.
                      +1

                      На самом деле, как человек ведущий домашнюю бухгалтерию более 10 лет, скажу, что разбивка чека по категориям — не нужна. Зачем вам такая детализация? Какую полезную информацию вы получаете из такой детализации?


                      Мой опыт такой, что разбивка по массе узких категорий — это большие затраты труда, которые не приносят ощутимых дивидендов. Например, часто в супермаркете покупаю вместе с продуктами несколько журналов. Можно конечно каждый раз разбивать чек на две категории: продукты и журналы. На практике же, никакой пользы от такой разбивки нет. Что я, журналы вдруг перестану покупать. Я покупаю три журнала: «Мото», «Мотоэксперт» и «Наука и жизнь». Каждый год трачу на это приблизительно одинаковую сумму, в пределах 400-600 рублей в месяц. Зачем мне эта информация в отдельной категории?


                      Изначально я тоже пытался каждый чек бить и каждую категорию учитывать отдельно. Но это превращает учет в пытку, а пользы — ровно 0.

                        0
                        Это позволяет делать выборку по категориям по приходу / расходу. Возможно может показаться бесполезным, но это используется в дальнейшем при фильтрации для рисования графиков и прочего. Позволяет в размышлениях, что на что было потрачено. :)
                          +1

                          Ценность этой информации минимальна, на самом деле. И без того количество категорий достаточно большое, чтобы еще и чеки из супермаркета бить. Никакой информации для принятия решений из этого не извлечь.


                          Допустим, меня интересуют в домашнем учете следующие вопросы:


                          • сколько всего зарабатываю
                          • сколько всего трачу
                          • сколько денег у меня сейчас
                          • сколько трачу на какие-то регулярные повторяющиеся вещи: в среднем на продукты в месяц, на коммунальные услуги, на содержание авто и мотоцикла

                          Первые два вопроса — самые важные, так как позволяют принимать какие-то долгосрочные решения. Например, сколько в месяц я могу откладывать на какую-то очень большую затрату и сколько месяцев/лет мне понадобится (путешествие, новый мотоцикл, еще что-то из этой категории). Ответ на третий вопрос часто бывает нужен, чтобы принять решение о какой-то внезапной трате. Ответ на последний вопрос — чтобы скорректировать какие-то ежемесячные траты, например, на мобильную связь.


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

                            0
                            Еще раз — эта информация важна в моем конкретном случае, даже если это не важно кому-то еще. Ну и это все автоматизировано — сказать одно короткое слово в конце фразы — ничего утомительного. Доход позволяет не думать о мелких расходах, но возможность разбивки по категориям ничего фактически не стоит в плане занесения, а так же было в списке требуемых фич в ТЗ основного пользователя — жены.
                              0
                              Например, потратил в магазине продуктовом 20к в месяц. Понял. что что-то многовато. Построил по категориям, выявил существенные расходы и выяснил, что оказывается каждый день покупалась баночка колы (вот просто так), а так же какой-то дорогой сырок, от которого ни холодно ни жарко, но который сожрал 2000р за месяц (а его аналог уже 1000 всего лишь). В итоге уже экономия в 2000 — 3000 рублей.

                              Вручную заносить действительно сложно, но когда есть автоматизированный инструмент, то почему бы и нет. Если бы по такой схеме (сколько всего зарабатываю / сколько всего трачу) работали в рекламных сетях, то все бы разорились. Сотни рекламных кампаний, тысячи объявлений, брать в расчёт нужно конкретное объявление или кампанию, а не весь аккаунт.

                              P.S. это естественно актуально до определённого уровня заработка. Дальше просто смысла нет пытаться сэкономить 5-10% (хотя кто знает). Но учитывая средний уровень заработка по России, то всем очень даже пригодится автоматическое разбиение по категории.

                              P.P.S. Таким образом можно избавить себя от внезапных ненужных трат — поход по магазинам, когда всё есть и выброс 5-10к на вещи. Поход куда угодно, что не особо то и нужно было. Как раз в этом случае детализация позволит выявить такие траты, а в сколько всего тратится будет только общая информация, но никак не полезность покупок или трат.
                                0

                                На эту тему есть хороший анекдот:


                                Стоит прилично одетый мужчина в Нью-Йорке возле небоскреба и курит.
                                Подходит к нему журналист и говорит:
                                — Здравствуйте. я корреспондент газеты «Нью-Йорк Таймс». Можно задать
                                вам несколько вопросов?
                                — Да задавайте, я в принципе не спешу.
                                — Вот вы курите. А, простите, как долго вы курите?
                                — Мне сейчас 43, и курю я с 16 лет.
                                — А какие сигареты вы курите, если не секрет?
                                — Да не секрет — «Мальборо».
                                — И последний вопрос — сколько сигарет в день?
                                — Пачки полторы — две.
                                Журналист достает калькулятор, что-то считает и снова обращается
                                к мужчине:
                                — Вот вы знаете, если бы вы не курили, то на сэкономленные деньги
                                вы могли бы купить вот этот вот небоскреб?
                                — Серьезно?.. А вот вы сами курите?
                                — Нет, я не курю.
                                — И что, небоскреб у вас есть?
                                — Нет, небоскреба у меня нет.
                                — А я курю, и небоскреб мой…

                                  0
                                  Пример с едой показателен, но только для начала карьеры.
                                  Я во время учебы в ВУЗе и сразу после окончания вел такую штуку…

                                  В иные месяца:
                                  50% уходило на аренду квартиры,
                                  25% уходило на печенки и 25% уходило на пиво…
                                  ;)

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

                                  В середине декабря получил 270 тыс. руб.
                                  Но они куда-то делись до 5 января (не пил).
                                  Решил, что пора снова, как в студенческие годы, вести аналитику.

                                  P.S.:
                                  Все хорошо по ситуации.
                                  Считать каждую булочку важно только когда ты студент.
                                    0
                                    А еще можно просто ужасаться, куда делось 300к за 2 месяца, хотя вроде ничего такого серьезного не покупалось :) Статистика в первую очередь носит информационный характер, а принимаются решения или нет — это другой вопрос.
                                      0
                                      Связанный.
                                      Решения ты принимаешь на основе чего либо.
                        0
                        1) У многих банков есть мобильные приложения, а они доступаются к данным через API, вот и получаем простой способ импортировать в свою систему все траты. Например вот https://rockapipreview.surge.sh/operations/, еще ковырялся в API tinkoff.ru, там тоже все просто. На 99% уверен что сбербанк, альфабанк, втб, юникредит тоже можно импортировать.
                        2) внести пару покупок в месяц руками не так сложно
                        3) см. п. 1
                          0
                          См. комментарий выше — сумма, к сожалению, приезжает одним куском, без разбивки на товары.
                            0
                            Тоже не сильно страшно, как правило: один магазин — одна категория, причем заранее известная. Бывают исключения, но редко.
                              0
                              Ну вот, например, алкоголь хочется считать отдельно от «еды», как быть? Ну и т.п. случаи. :)
                          0
                          Живу в замкадье, карточек много, разных банков, выводы такие:
                          Для покупок используется одна, с которой бонусы жирнее. Другие карты используются в особых случаях. И не представляю сценария, по которому я буду еду покупать сегодня с одной карты, а завтра с другой.
                          Шиномонтаж — в идеале это две операции в год. Я понимаю, что это пример, но основные расходы — это продукты/бензин/кафешки и прочие развлечения, которые оплачиваются картой. Несколько месяцев в кошельке лежали пара сотен рублей, пока не спустил на жетоны в автомойке, вот куда еще эквайринг не пришел, кстати.
                          0
                          Наоборот!
                          Можно взять выписку из банка (желательно CAMT) и привязывать к расходам чеки!
                            0
                            Попробуйте Office Lens (https://play.google.com/store/apps/details?id=com.microsoft.office.officelens&hl=ru) умеет исправлять перспективу документа и экспортировать в OneNote который уже в свою очередь распознает документ. Есть под все основные платформы.
                            0
                            А в Казахстане многие (а может даже и все) кассы подвели к общей системе.
                            В чеке пишут URL и контрольный номер. Через сайт и контрольный номер можно этот чек пробить через сайт обратно: https://consumer.oofd.kz/.
                            Причем некоторые магазины предоставляют более подробную информацию о покупке чем другие (номенклатура).
                            Только как-то оно всё непонятно зачем. API нет, чтоб пробить чек надо вбить все данные (включая контрольный код, время и общую сумму). Видимо сделано, чтоб можно было убедиться, что магазин не скручивает чеки или другим способом уклоняется от уплаты налогов. И если покупатель чека не найдет в базе, то он может магазин заложить.
                              0
                              В Канаде всего один магазин Home Depot разпознает дебитовую кароточку и посылает на зарегистрированный email версию чека
                              0

                              Просто хочу напомнить, сто с 2017 года на территории РФ действует новая редакция ФЗ-54, согласно которой для большинства ритейл операций онлайн фискализация является обязательной. Так что теперь на чеке должен ьыть qr код со ссылкой на чек в электронном виде.

                                0
                                То есть все магазины обязаны быть подключены к интернету?
                                И если интернет пропадает — продавать товары нельзя?
                                  0
                                  Да, за исключением «труднодоступных мест», список которых будет обудликован позднее, все должны иметь доступ к интернет. Если саязь разорвана, то продажи можно осущетвлять в течение определенного времени (в законе данный промежуток не указан, но производители оборудования ориентируются на приблизительно 30 дней), при восстановлении связи данные будут переданы Оператору Фискальных Данных
                                  0
                                  Уже для всего сделали? Раньше точно было для некоторых видов алкоголя. На чеке выбивали qr код и сразу url, где можно было посмотреть все это.
                                    0
                                    Да, теперь для практически всех видов товаров.
                                    Исключение:
                                    банки, газетные киоски, обувные ателье, столовые в учебных учреждениях, пункты приема стеклопосуды и утильсырья, торговля на рынках и ярмарках, а также такие виды деятельности, как продажа ценных бумаг, продажа проездных билетов в общественном транспорте, торговля из автоцистерн, разносная торговля, изготовление и ремонт металлической галантереи и ключей, присмотр и уход за детьми, больными, престарелыми и инвалидами, продажа предметов народного художественного промысла
                                  0
                                  Прикольно, но вроде были такие приложения, хотя могу и ошибаться
                                    0
                                      0
                                      По работе пользуемся сервисом Expensify для заполнения трат — там в мобильном клиенте есть такой функционал: сфоткал чек и готово.
                                        0
                                        Как насчет просто воспользоваться Expensify, доступным для частным лиц по бесплатной подписке?
                                          0
                                          Немного офтопик, но в продолжение темы учёта совместных трат.

                                          Я начинал с таблицы с набором формул для автоматического выведения итогового баланса (если будет интерес, могу описать свой подход подробнее).

                                          Пробовал также разные специализированные приложения: Splitwise, Kittysplit. Все они, к сожалению, оказались неудобны в том либо ином аспекте. Где-то нужно заводить акаунты для каждого участника поездки, где-то нет офлайн-режима.
                                          Также я не видел ещё ни одного приложения, где можно было бы объединять участников в «семьи», чтобы считать баланс «на семью», а не на каждого человека. А ещё могут быть разные валюты…

                                          В итоге я набросал для себя простенькое SPA с хранением данных в localStorage. Планы были большими (шаринг, мульти-валютность, «семьи», подтверждение транзакций другими участниками), но так пока и остались планами.

                                          Что касается конкретно распознавания, то для чеков из ресторанов было бы удобно выделять не только итоговую сумму, но и отдельные позиции. Чтобы потом можно было их удобно раскидать по участникам без ручного ввода сумм в калькуляторе.
                                            0
                                            Ну и совсем уж офтопик порекомендую приложение для катания, которое я открыл для себя в этом сезоне — Maprika

                                            Привязывает GPS-координаты к скану бумажной карты региона. Записывает трек с возможностью последующей автоматической (!) разбивки статистики по подъёмникам и трассам. Если объединиться в группу, будет показывать положение каждого участника на карте (также можно добавлять маркеры а-ля «обедаем здесь в 12:00»).

                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                          Самое читаемое