Привет. Я бы тут делал так: n8n принимает PDF или фотку чека, гонит файл в OCR, вытаскивает продавца, дату, номер документа, валюту и сумму, потом нормализует поля и закидывает всё в Google Sheets. На практике это реально экономит часы ручной рутины, особенно когда чеки сыпятся из почты, мессенджера или общей папки.
В этой статье покажу рабочую схему, на каких нодах её собирать, как развести PDF и фото по разным веткам, где чаще всего всплывают косяки с OCR и что сделать, чтобы таблица не пухла от дублей. Плюс дам пример структуры полей, кусок кода для нормализации и чек-лист перед запуском.
Кому пригодится: мастерским, небольшим сервисам, бухгалтерам на потоке, продавцам на маркетплейсах и всем, кто устал копировать суммы руками из сканов и файлов.
Содержание
- Что получится на выходе
- Как выглядит workflow в n8n
- Какой OCR брать под чеки и счета
- Какие поля лучше сразу складывать в таблицу
- Как не словить дубли и кривые суммы
- Где чаще всего ломается схема
- Чек-лист перед запуском

Что получится на выходе
Если собрать это дело нормально, на выходе у тебя будет не просто кучка распознанного текста, а аккуратная табличка с понятными колонками: дата документа, тип документа, продавец или контрагент, номер, валюта, сумма, налог, ссылка на исходный файл, статус проверки и техничный ключ для дедупликации. А если захочешь, можно ещё разворачивать позиции товара в отдельные строки.
Я обычно делаю два режима. Первый — одна строка на один документ, когда важна общая сумма. Второй — одна строка на одну позицию, если потом нужно считать категории, закупки или сверять состав счета. Для первого режима workflow собирается быстрее. Для второго приходится чуть дольше поковыряться с массивом items, зато аналитика потом куда приятнее.
Если уже работаешь с n8n, можешь заодно подсмотреть мой материал про вебхуки и защиту от дублей запросов. Там ровно тот участок, на котором новички чаще всего наступают на грабли при приёме файлов.
Как выглядит workflow в n8n
Я люблю простую, читаемую схему, чтобы потом не сидеть ночью и не вспоминать, где именно поломалась ветка с фотками. Каркас у меня обычно такой:
- Триггер: Webhook, Google Drive Trigger, Gmail Trigger, Telegram Trigger или папка на диске.
- Получение бинарного файла и служебных полей: имя, MIME-тип, размер, ссылка на исходник.
- Ветка по типу файла: PDF отправляю в одну сторону, JPG/PNG/HEIC — в другую.
- OCR или document AI: получаю текст или уже полуготовые поля.
- Нормализация через Edit Fields или Code.
- Проверка обязательных полей: дата, сумма, поставщик.
- Проверка дублей по своему ключу.
- Append row в Google Sheets.
- Логирование статуса и уведомление, если документ не распознался как надо.
Вот тут важный момент. Если PDF текстовый, иногда хватает простого извлечения текста и дальнейшего парсинга. Но если это скан, мятый чек с телефона или счёт в виде картинки внутри PDF, я сразу иду в OCR-сервис, а не пытаюсь выжать чудо из обычного чтения PDF. Так стабильнее.
Для развилки по файлам ставлю If или Switch: если MIME содержит pdf — маршрут на обработку документов; если image — на ветку фото. Это полезно ещё и потому, что разные OCR-движки по-разному едят входные данные. В одной ветке можно ждать многостраничный файл, в другой — одиночное фото с перспективой и тенями.
Логику записи в таблицу удобно сверять с материалом про обработку данных в Google Sheets через n8n. Там принцип тот же: сначала приводим поля к чистому виду, потом уже пишем строку, а не наоборот.
Какой OCR брать под чеки и счета
Тут я бы не женился на одном сервисе навсегда. Под разные задачи заходят разные варианты. Ниже короткая таблица, как я обычно выбираю движок.
| Вариант | Когда беру | Чем нравится | На что смотрю внимательно |
|---|---|---|---|
| Mistral OCR | Сканы, фото, многостраничные PDF | Хорошо вытаскивает текст документа целиком | После OCR всё равно прогоняю через схему полей |
| Mindee | Когда нужен именно invoice/receipt OCR | Умеет сразу отдавать поля документа | Проверяю, все ли нужные поля есть в ответе |
| AWS Textract | Если уже живёшь в экосистеме AWS | Неплохо работает по счетам | Схема становится тяжелее по настройке |
| OpenAI + схема полей | Когда нужен гибкий разбор текста и фото | Удобно просить сразу JSON нужного формата | Важно жёстко задать структуру ответа |
| Google Drive OCR как запасной вариант | Когда нужен бюджетный черновой проход | Быстро проверить гипотезу | На таблицах и кривых сканах бывает капризным |
Мой совет такой: если задача звучит как распознавание чеков по фото, OCR чеков PDF или извлечение данных из счета в таблицу, я сначала смотрю на Mistral OCR или Mindee. Они ближе к реальной задаче, чем голое выдёргивание текста. А уже потом поверх этого можно навесить Information Extractor, Structured Output Parser или обычную LLM-цепочку, чтобы привести ответ к единому JSON.
Если хочется стартануть быстрее, глянь подборку готовых шаблонов n8n. Часто проще взять каркас, чем собирать всё с нуля и потом искать потерявшийся бинарник между нодами.
Какие поля лучше сразу складывать в таблицу
Самая частая ошибка — тащить в таблицу весь распознанный хаос. Не надо. Таблица любит порядок. Я обычно держу такой набор колонок:
- source_filename
- source_url
- document_type
- vendor_name
- document_number
- document_date
- currency
- subtotal
- tax
- total
- payment_method
- items_json
- ocr_text
- dedupe_key
- parse_status
- review_comment
- created_at
Зачем так много? Потому что через месяц ты сам себе скажешь спасибо. Когда OCR внезапно распознал общую сумму как номер счёта, поле review_comment спасает нервную систему. А items_json помогает не терять позиции товара, даже если в основную таблицу пишешь только одну строку на документ.
Для чеков я обычно добавляю ещё merchant_category или expense_type, если дальше нужен учёт расходов. Для счетов полезно поле due_date и отдельный статус: received, parsed, needs_review, approved. Тогда по таблице уже можно строить отчёты, напоминания и ежедневные сводки.
Как просить ИИ вернуть чистую структуру
Я формулирую задачу жёстко: верни JSON, где есть document_type, vendor_name, document_number, document_date, currency, total, tax и массив items. Если какого-то поля нет, верни null, а не фантазию. Это важнее, чем красивая формулировка промпта. Документный поток любит дисциплину.
Если потом захочешь на этой базе собирать уведомления, пригодится и схема про автосводку из Google Sheets в Telegram: там уже можно собрать ежедневный дайджест по новым чекам и счетам.
Как не словить дубли и кривые суммы
Вот здесь начинается взрослая жизнь. Один и тот же файл может прилететь дважды: из почты, из папки и ещё вручную через форму. Плюс люди любят пересылать один и тот же чек повторно. Поэтому я почти всегда делаю dedupe_key.
Самый практичный ключ — это склейка из названия продавца, номера документа, даты и нормализованной суммы. Если номер документа пустой, тогда беру vendor + дата + сумма + имя файла. Неидеально, но в бытовом потоке работает очень бодро.
return items.map(item => {
const j = item.json;
const total = Number(
String(j.total ?? '')
.replace(',', '.')
.replace(/[^\d.]/g, '')
);
const dedupeKey = [
(j.vendor_name || '').trim().toLowerCase(),
(j.document_number || '').trim().toLowerCase(),
(j.document_date || '').trim(),
Number.isFinite(total) ? total.toFixed(2) : ''
].join('|');
return {
json: {
...j,
total_normalized: Number.isFinite(total) ? total : null,
dedupe_key: dedupeKey
}
};
});
Дальше этот ключ гоню в Remove Duplicates. Если поток идёт постоянно, очень удобно включать проверку не только внутри текущего запуска, но и между предыдущими исполнениями workflow. Так ты перестаёшь плодить повторные строки в таблице после случайных перезапусков.
Ещё один момент — формат суммы. OCR легко путается в запятых, пробелах и символах валюты. Поэтому на входе в Google Sheets я всегда держу отдельное число total_normalized и отдельно currency. Не надо складывать их в одну ячейку вида 1 250,50 руб., если потом хочешь что-то считать формулами.
Где чаще всего ломается схема
Я чаще всего вижу пять типовых проблем.
- Фото снято под углом, часть текста ушла в перспективу.
- На чеке бледная термопечать, и OCR съедает цифры.
- В PDF лежит картинка, а не текст, а человек думает, что это обычный PDF.
- ИИ выдумывает номер документа, когда его нет.
- Google Sheets получает поля в разном формате и строки едут криво.
Лечится это довольно приземлённо. Для фото — добавить шаг с проверкой качества или хотя бы отправлять такие документы в ручную проверку. Для бледных чеков — хранить сырой OCR-текст и ссылку на файл. Для фантазий модели — требовать null вместо догадок. Для таблицы — держать одну жёсткую схему колонок и не менять её на лету.
Отдельно советую собрать ветку ошибок с уведомлением. Очень выручает сценарий по контролю ошибок в n8n: retries, error workflow и нормальное оповещение экономят кучу времени, когда OCR-сервис внезапно отвечает не тем, что ты ждал.
Чек-лист перед запуском
- Определи, откуда прилетает файл: папка, почта, форма, бот, webhook.
- Разведи PDF и фото по разным веткам.
- Выбери OCR-провайдера под свои документы, а не по красивому демо.
- Задай жёсткую схему JSON-полей.
- Нормализуй дату, сумму и валюту до записи в таблицу.
- Сделай dedupe_key и включи проверку дублей.
- Пиши в таблицу только чистые поля, сырой текст храни отдельно.
- Добавь статус needs_review для сомнительных документов.
- Настрой уведомление об ошибке и ручную точку контроля.
Итог
Если по-человечески, то n8n для распознавания счетов и чеков — это не какая-то космическая история. Рабочая связка давно понятна: приняли файл, прогнали через OCR, вытащили поля в единый JSON, проверили обязательные значения, убрали дубли и записали строку в таблицу. Самое важное тут не сам OCR, а аккуратная нормализация и дисциплина в структуре данных.
Я бы начинал с минимального конвейера на одну строку в таблице, а уже потом докручивал позиции товаров, категории расходов, сводки и уведомления. Так ты быстрее увидишь результат, поймаешь реальные ошибки на своих документах и не утонешь в лишней сложности на старте.
Когда эта схема завелась, она уже начинает работать как нормальный цех: документы заходят, данные падают в таблицу, а ты занимаешься делом, а не копипастой дат и сумм из сканов.