42 PDF, 532 страницы: как парсить прайсы и не терять цены в 2026

· ·

42 PDF, 532 страницы: как парсить прайсы и не терять цены в 2026

PrimeCoder · 2026 · формат: tech

Разбор новинки простыми словами: что это, кому нужно и брать ли.

Показывает, что извлечение цен и тиражей из PDF требует координатной привязки слов, а не порядка текста — иначе тихие ошибки искажают закупочную аналитику SMB.

Связанные услуги: каталог, AI Boost Team, стать клиентом.

Задача на вечер, которая не закрылась за вечер

Мастерская за год собрала папку коммерческих предложений: 42 PDF, 532 страницы, 650 мегабайт. Прайсы, презентации, отдельные файлы под конкретных заказчиков. Из всего массива нужна одна таблица: позиция, тираж, цена за штуку. Ответ на вопрос, насколько дешевеет изделие при росте тиража с 10 до 200 штук и одинаково ли это работает для футболки и для стикеров.

Ожидание: вечер работы. Снять текст, найти числа рядом со словом «шт», сложить. Реальность: почти каждая ошибка по дороге оказалась тихой.

Скрипт отрабатывал без исключений и выдавал правдоподобные числа, которые не совпадали с тем, что напечатано на странице.

Дальше разбор того, почему извлечение цен из прайсов в 2026 упирается в геометрию листа, а не в регулярные выражения.

Порядок текста — не порядок на листе

PDF хранит не строки и колонки, а последовательность операторов вывода. Блок «50 шт» двигали в макете последним, и в потоке он оказался в конце. Парсер, который читает текст подряд, честно склеил третью цену с третьим тиражом.

Счёт на 38 страницах с ценами: разбор по порядку текста через pypdf дал 17 ошибок, через pdfplumber — одну, привязка цены к ближайшей метке тиража по координатам слов — ноль.

Футболка из одного прайса: 680 ₽ за 10 штук, 610 ₽ за 50, 550 ₽ за 200, а в колонке «от 201 шт» вместо числа стоит «цена согласовывается». Наивный разбор выдал 10 шт → 680, 200 шт → 610, от 201 шт → 550. Цена за 50 штук уехала в колонку «200 штук». Термокружка оттуда же: 885, 792, 978 ₽ — самая высокая цена встала рядом с самым большим тиражом.

Порядок, в котором дизайнер расставлял надписи, с порядком на листе никак не связан: колонку «50 шт» в макете, видимо, двигали последней, и в потоке она оказалась в конце.

Подмена инструмента сама по себе не лечит. На одной странице число 680 стояло на несколько пунктов выше своего «РУБ», pdfplumber разнёс их по разным строкам, между ними попала метка «10 шт.», и футболка за десяток стала стоить 610. Отсюда рабочее правило: не доверять никакому порядку текста, только расстоянию между рамками слов.

31% страниц вообще без текста

Первый проход ничего не парсит, он считает, где текст есть. Страница, с которой снимается меньше 30 символов, считается пустой. Итог по папке: 166 страниц без текста из 532, это 31%; 7 файлов целиком из картинок; у 21 файла хотя бы одна страница пустая. В 14 файлах картинками стали отдельные страницы, обычно самые нужные, с ценой.

Второй молчаливый сбой — шрифты без таблицы ToUnicode. Кириллица приходит именами глифов вида uni041F: шесть файлов, 1850 битых символов. Замена лечится в одну строку, номер символа уже лежит в имени. Пока её нет, файлы выпадают из выборки без единого исключения: поиск по слову «футболка» просто ничего не находит, хотя футболка есть на каждой странице.

Хуже половины сломанной страницы — половина целой. Заголовок набран шрифтом с таблицей соответствия, тело — без неё. При беглом просмотре файл выглядит прочитанным.

Сверка двух прайсов: цены сошлись, тиражи нет

Когда оба файла прочитались, позиции сопоставили по тройке цен. Нашлось 13 общих позиций, у 10 совпали и цены, и тиражи. У трёх цены одинаковые, а шкала разная. Бутылка для воды 606 / 550 / 491 ₽: в январском файле 150 / 200 / 500 шт, в февральском 10 / 50 / 200 шт. Термокружка 978 / 885 / 792 ₽ и стикерпак 115 / 52 / 35 ₽ — та же картина.

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

Скрипт здесь сделал своё дело: показал расхождение, которое при чтении глазами одного документа заметить невозможно.

В февральском прайсе 19 позиций со шкалой 10 / 50 / 200 шт. Поставщик за квартал мог переписать сетку тиражей, и по одному файлу этого не видно. Видно только при сверке.

Кому это нужно и как применить

Тем, кто закупает мерч, сувенирку, полиграфию, упаковку и сравнивает предложения руками в таблице. Экономика считается на единицу: 9.750 ₽ за 25.000 пакетиков соли — 0,39 ₽ за штуку; 29.500 ₽ за 540 упаковок по 100 салфеток — 0,55 ₽ за салфетку. Ошибка в колонке тиража ломает сравнительную таблицу целиком: вы сопоставляете цену за 200 штук с ценой за 50 и делаете вывод о скидке, которой нет.

Две ловушки формата. «9.750 ₽» означает тысячи, а не копейки. Цена может стоять за партию, а не за штуку. Парсер не различает это без явных правил.

Где подвох

  • 31% страниц без текстового слоя. Без распознавания картинок эти цены не достать, в разборе их оставили за скобками.
  • Метки «10 шт» и «50 шт» стоят то в строку, то в столбик. Одна и та же футболка в двух прайсах свёрстана по-разному, ось сравнения приходится определять на ходу.
  • Цена и «РУБ» могут быть разными словами, а подпись склеивается со следующей строкой в «550 РУБСОСТАВ».
  • В ячейке вместо числа — «цена согласовывается». Регулярка такое не поймает и молча подставит соседнее значение.

Брать или подождать: вердикт

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

Что сделать на этой неделе

  1. Прогнать папку вслепую: посчитать страницы, где текста меньше 30 символов, и файлы с именами глифов. Это карта дыр, ещё не парсинг.
  2. Взять один прайс с известными ценами и сверить вывод скрипта с картинкой страницы руками.
  3. Заменить разбор по порядку текста на привязку цены к ближайшей метке тиража по координатам слов.
  4. Добавить правила формата: «9.750 ₽» — тысячи, «за партию» — делить на количество.
  5. Сверить свежий прайс с предыдущим отдельно по ценам и отдельно по тиражам.

Частые вопросы

Можно просто взять pdfplumber и не мучиться?

Одна ошибка на 38 страниц вместо 17. Не ноль. Причина в том, что число и подпись «РУБ» разъехались по строкам, и цена потерялась.

Почему поиск по слову «футболка» ничего не находит?

У шрифта нет таблицы ToUnicode, кириллица приходит именами глифов. Лечится заменой имени на символ по номеру.

Что делать с 166 страницами-картинками?

Распознавать. Иначе цены с них не попадут в таблицу, а вы об этом даже не узнаете.

Обязательно программировать?

Для разовой сверки хватит и ручной выборки. Для регулярной работы с прайсами скрипт окупается на первом же расхождении тиражей.

Проверьте свои прайсы на смещение колонок. Возьмите последний файл от поставщика, выпишите три цены с картинки страницы и сравните с тем, что достал парсер. Если совпало не всё, у вас в таблице уже живут чужие цифры.

Читайте также