Большинство процессов в нашем современном мире стремится к автоматизации. Хотелось бы разместить здесь свою наработку. Надеюсь данный материал найдёт своего читателя. В данной статье рассмотрим автоматизацию введения ежедневных отчетов компании.
Какие проблемы решает скрипт?
-
Избавление сотрудника от рутинной задачи.
-
Минимизация ошибок, которые мог бы случайно допустить человек.
-
Оптимизация затрат компании, сократить расходы на содержание штата сотрудников: менеджеров и бухгалтеров.
В данной статье я хочу поделиться, как можно автоматизировать процессы внутри компании с помощью моего скрипта.
Архитектура скрипта
Архитектуру, которую вы видите на рисунке 1, очень примитивная. Данный скрипт находится в режиме разработки, сейчас он хорошо обрабатывает изображения с транзакциями Сбербанк.
Для работы с изображением я использовал следующие библиотеки:
-
Tesseract – это библиотека JavaScript, которая извлекает из изображений слова практически на любом языке.
-
Sharp – это библиотека JavaScript, которая обрабатывает фото, на примере увидим, что она конкретно выполняет.
Дополнительно: Для вывода логов я использовал библиотеку Pino.
Описание кода
-
Обработка изображения.
-
Распознавание текста на изображении с помощью OCR.
-
Извлечение и подсчёт финансовых данных.
Давайте посмотрим файлы в директории utils .
logger.js
import pino from 'pino'; import pretty from 'pino-pretty'; export const logger = pino(pretty({ colorize: true, levelFirst: true, }));
Pino предоставляет дополнительную функциональность и гибкость + в некоторых проектах линтеры могут запрещать использование console.log .
preload.js
import { fileURLToPath } from 'url'; import path, { dirname as pathDirname, resolve } from 'path'; import sharp from 'sharp'; const filename = fileURLToPath(import.meta.url); const dirname = pathDirname(filename); export const getPath = (relativePath) => { const ROOT_PATH = path.join(dirname, '../'); return resolve(ROOT_PATH, relativePath); }; export const preload = async (input, output) => { return await sharp(input) .resize(1200) .grayscale() .normalize() .sharpen() .toBuffer(); };
В этом коде мы используем библиотеку sharp, которая предназначена для обработки изображений в Node.js.
Что мы здесь делаем?
Изменяем размер изображения, делаем картинку черно-белой, улучаем контрастность, повышаем резкость => сохраняем результат в output.
Для чего мы это делаем?
Улучшаем визуальное качество нашего изображения. Тестирование показало, что не все транзакции распознает Tesseract.
Рассмотрим главный файл app.js.
app.js
import Tesseract from 'tesseract.js'; import { preload, getPath } from './utils/preload.js'; import { logger } from './utils/logger.js'; import { keywords } from './keywords.js'; const input = getPath('./assets/input.jpg'); const run = async (input) => { const output = await preload(input); try { const { data: { text } } = await Tesseract.recognize(output, 'rus', { logger: info => logger.info(info.status) }); const amounts = []; const priceWithRRegex = /[+-]?\d+(?:[\s,]\d{3})*(?:[.,]\d+)?\s*Р/g; let ignoreNext = false; text.split('\n').forEach(line => { if (keywords.some(keyword => line.includes(keyword))) { ignoreNext = true; } if (!ignoreNext) { const priceMatches = line.match(priceWithRRegex); if (priceMatches) { priceMatches.forEach(priceMatch => { let price = priceMatch .replace(/\s/g, '') .replace(',', '.') .replace('Р', '') .trim(); if (!price.startsWith('+') && !price.startsWith('-')) { price = '-' + price; } const numericPrice = parseFloat(price); if (!isNaN(numericPrice)) { amounts.push(numericPrice); } }); } } if (ignoreNext) { ignoreNext = false; } }); const total = amounts.reduce((acc, curr) => acc + curr, 0); return { amounts, total }; } catch (error) { logger.info(error); throw error; } }; run(input).then(result => { logger.info(result, 'Result: '); });
Сначала вызывается функция preload, которая выполняет обработку изображения. Как я писал раннее, это нам нужно для того, чтобы улучшить качество распознавания текста.
Обрабатываем изображение с помощью Tesseract. Текст, который мы получили, разбивается на строки. Используя регулярное выражение priceWithRRegex, мы ищем в каждой строке суммы, обозначенные символом «Р». Также я задал keywords , после этих ключевых слов сумма не входит в массив. Например, общая сумма за день.
В итоге, после обработки данных мы получаем массив транзакций и их общую сумму.
Код всего проекта на GitHub.
Тестирование
Давайте на примере данного изображения рассмотрим, как работает скрипт.
Изображение, которое мы будем обрабатывать:
Обработанное изображение:
После обработки изображения идет извлечение текста и получение всех транзакций. В итоге мы получаем массив транзакций и их общую сумму.
Заключение
Данный пример хорошо показывает, как с помощью такого скрипта автоматизировать процесс ведения ежедневного отчёта. Он решает проблемы, описанные в статье, и упрощает работу с финансовыми данными. Данный скрипт находится в этапе разработки, было бы хорошо его дорабатывать вместе с другими разработчиками. В ближайших планах — добавить поддержку распознавания транзакций с других банков, которые используют несколько отличающийся формат данных. В будущем можно интегрировать этот скрипт с другими системами, такими как МойСклад, что позволит автоматизировать ещё больший объём работы, включая синхронизацию данных с бухгалтерскими системами, управление складскими остатками и улучшение общего управления бизнесом.
ссылка на оригинал статьи https://habr.com/ru/articles/838328/
Добавить комментарий