Чтение и извлечение текста из PDF

PDF — формат, в котором приходят счета, договоры и выписки. Библиотека pypdf открывает их из Python и достаёт текст постранично, чтобы дальше обработать его регулярками.
Суть: PdfReader(file) открывает PDF, reader.pages — список страниц, page.extract_text() возвращает текст страницы. Дальше — уже знакомый re.

Огромный пласт рутины — это PDF: вытащить суммы из счетов, собрать данные из десятков выписок, найти пункт в договоре. Раньше для PDF использовали PyPDF2, но современный поддерживаемый преемник — pypdf (ставится как pip install pypdf). Он умеет читать текст, метаданные, объединять и разбивать документы.

Извлечение устроено просто: открываете файл через PdfReader, перебираете reader.pages и для каждой вызываете extract_text(). Полученный текст — обычная строка, к которой применимы регулярки из прошлого урока. Поскольку pypdf нет в браузере, код пойдёт во врезках language-text.

from pypdf import PdfReader

reader = PdfReader('invoice.pdf')
print('Страниц:', len(reader.pages))
print('Автор:', reader.metadata.author)

# Собираем весь текст
full_text = ''
for page in reader.pages:
    full_text += page.extract_text() + '\n'

# Дальше — знакомые регулярки
import re
total = re.search(r'Итого:\s*([\d ]+)', full_text)
print('Сумма счёта:', total.group(1).strip())

Самое ценное здесь — что после extract_text() вы возвращаетесь к чистому Python. Разбор извлечённого текста — это re и обработка строк, которые полностью исполнимы в браузере. Смоделируем разбор текста, «как будто» он пришёл из PDF.

Попробуй сам ▶

import re

# Текст, который вернул бы extract_text() для счёта
pdf_text = '''ООО Ромашка
Счёт № 2026-118 от 22.06.2026
Ноутбук          75000
Мышь              1200
Итого: 76200 руб'''

# Номер и дата счёта
head = re.search(r'Счёт № (\S+) от (\S+)', pdf_text)
print('Счёт', head.group(1), 'от', head.group(2))

# Все позиции: название + цена
for name, price in re.findall(r'([А-Яа-я]+)\s+(\d+)', pdf_text):
    print(f'  {name:10} {int(price):>6} руб')

total = re.search(r'Итого:\s*(\d+)', pdf_text)
print('Проверка итога:', total.group(1))
КОНВЕЙЕР ОБРАБОТКИ PDF

  invoice.pdf
     |  PdfReader
     v
  страницы [0..N]
     |  extract_text()
     v
  сырой текст (str)
     |  re.findall / search
     v
  номер, дата, сумма  ->  в таблицу/отчёт

На практике извлечение из PDF — это всегда диалог с конкретным форматом документа. Счета одного поставщика свёрстаны одинаково, и шаблон под них пишется один раз, после чего работает на сотнях файлов. Но стоит сменить поставщика — и вёрстка другая, и регулярки нужны новые. Поэтому реалистичный подход такой: сгруппируйте документы по типу, под каждый тип напишите свой разбор, а на входе определяйте тип по характерному признаку (например, по названию компании в шапке). Это превращает хаотичную пачку PDF в управляемый конвейер, где каждый документ попадает к «своему» парсеру.

Как работает под капотом

Внутри PDF текст хранится не как сплошная строка, а как набор операторов отрисовки: «поставь такие-то символы в такой-то точке страницы». extract_text() восстанавливает читаемый порядок, ориентируясь на координаты. Поэтому в сложной вёрстке (колонки, таблицы) порядок строк может получиться неожиданным — это не баг, а природа формата.

Отдельный важный случай — сканы. Если PDF — это картинка отсканированной бумаги, текста внутри нет вообще, и extract_text() вернёт пустоту. Такие документы требуют OCR (распознавания, например через tesseract), а это уже отдельная задача за рамками простого извлечения.

Частые ошибки

  • Ждать текст от сканов. Картинка-PDF не содержит текста; нужен OCR.
  • Рассчитывать на идеальный порядок строк. В многоколоночной вёрстке extract_text может перемешать фрагменты.
  • Использовать устаревший PyPDF2. Берите поддерживаемый pypdf.

Best practices

  • Сначала распечатайте сырой extract_text() и посмотрите, как реально лёг текст — потом пишите регулярки.
  • Закладывайтесь на пустой результат: проверяйте, что текст вообще извлёкся.
  • Для сканов отдельно подключайте OCR, не пытайтесь «выжать» текст из картинки.

Итоги. pypdf открывает PDF и отдаёт текст постранично, а дальше всё решают регулярки. Помните про сканы и про неидеальный порядок строк. Теперь научимся не только читать, но и собирать новые PDF.

Проверьте себя
1. Что вернёт extract_text() для отсканированного PDF (картинки страницы)?
AВесь текст идеально
BПустую строку — текста в картинке нет, нужен OCR
CОшибку чтения файла
DТолько метаданные
2. Какую библиотеку сегодня предпочитают для работы с PDF в Python?
APyPDF2 — единственный вариант
Bpypdf — поддерживаемый современный преемник PyPDF2
Copenpyxl
Dpython-docx