PDF — формат, придуманный для печати и просмотра, а не для хранения данных. Именно поэтому извлекать из него информацию надёжно сложнее всего среди всех форматов нашего обзора парсинга документов. В PDF приходят счета, договоры, спецификации, прайсы, банковские и государственные выписки — и почти всегда их нужно превратить в структурированные данные.
Главная развилка: текст или картинка
Первое, что определяет всю стратегию, — как именно текст хранится в файле. В «цифровом» PDF (сгенерированном из Word, верстки или браузера) текст лежит как выбираемые символы — его можно извлечь напрямую. В сканированном PDF страница это изображение, и без распознавания (OCR) символов в нём нет — извлечётся пустота. Проверить просто: если в просмотрщике текст выделяется мышью, он цифровой; если нет — нужен OCR. Эти два случая требуют совершенно разных инструментов, поэтому начинать всегда стоит с проверки.
Извлечение текста из цифровых PDF
Python
Для извлечения текста и, что важнее, таблиц лучший выбор — pdfplumber. Он понимает координаты символов и линий, поэтому умеет восстанавливать табличную структуру.
import pdfplumber
with pdfplumber.open("invoice.pdf") as pdf:
page = pdf.pages[0]
text = page.extract_text()
print(text)
for table in page.extract_tables():
for row in table:
print(row) # row — список ячеек строки таблицы
Когда нужен только текст и важна скорость, берут PyMuPDF (импортируется как fitz) — он очень быстрый и хорошо держит раскладку.
import fitz # PyMuPDF
doc = fitz.open("contract.pdf")
for page in doc:
print(page.get_text())
Для простых задач вроде извлечения текста постранично или работы с метаданными подойдёт pypdf (преемник устаревшего PyPDF2).
from pypdf import PdfReader
reader = PdfReader("report.pdf")
for page in reader.pages:
print(page.extract_text())
JavaScript / Node.js
В Node быстрый способ получить весь текст документа — pdf-parse.
const fs = require("fs");
const pdf = require("pdf-parse");
const buffer = fs.readFileSync("invoice.pdf");
pdf(buffer).then((data) => {
console.log(data.text); // весь текст
console.log(data.numpages);
});
Когда нужен низкоуровневый контроль или работа в браузере, используют pdf.js от Mozilla — он даёт доступ к отдельным текстовым фрагментам с их координатами.
Java
В корпоративных проектах распространён Apache PDFBox. Учтите смену API между версиями: в PDFBox 3.x документ открывается через Loader.loadPDF(...), тогда как в 2.x был PDDocument.load(...).
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import java.io.File;
try (PDDocument doc = Loader.loadPDF(new File("report.pdf"))) {
String text = new PDFTextStripper().getText(doc);
System.out.println(text);
}
Таблицы — отдельная боль
В PDF нет понятия «таблица»: то, что человек видит как таблицу, на самом деле набор текстовых блоков и линий с координатами. Поэтому извлечение таблиц всегда эвристика. pdfplumber восстанавливает их по линиям сетки и хорошо работает, когда таблица расчерчена. Для сложных таблиц без линий в Python применяют Camelot (метод по разметке) или tabula-py (обёртка над Java-движком Tabula). Если таблиц много и они однотипные, обычно подбирают один инструмент и калибруют его под конкретный макет.
Часто результат удобнее всего сразу выгрузить в таблицу — тогда дальнейшая обработка идёт через Excel или CSV, как с любым табличным источником.
Сканы и OCR
Если текст не выделяется, перед извлечением страницу нужно распознать. Классический стек в Python — рендер страниц в изображения (через тот же PyMuPDF) и распознавание движком Tesseract через обёртку pytesseract.
import fitz
import pytesseract
from PIL import Image
import io
doc = fitz.open("scan.pdf")
for page in doc:
pix = page.get_pixmap(dpi=300) # рендерим страницу в картинку
img = Image.open(io.BytesIO(pix.tobytes()))
text = pytesseract.image_to_string(img, lang="rus")
print(text)
Качество OCR сильно зависит от разрешения (берите от 300 DPI), чистоты скана и языка. Для русских документов обязательно указывайте языковой пакет rus. Стопроцентной точности от OCR ждать не стоит — результат почти всегда требует постобработки и проверки.
Когда PDF лучше не парсить «в лоб»
Иногда оказывается, что нужный документ существует и в другом формате — например, та же выписка доступна как CSV выгрузка или данные отдаёт API в JSON. Это почти всегда надёжнее, чем извлекать таблицу из печатной версии, поэтому стоит проверить источник, прежде чем браться за PDF.
PDF — формат, где «универсального» решения не существует: счёт, договор и скан требуют разных инструментов. Если у вас регулярный поток однотипных документов — счетов, актов, спецификаций — мы настроим извлечение данных из PDF под конкретный макет, включая таблицы и OCR для сканов, с выгрузкой результата в нужную систему.