Извлечение табличных данных из PDF с помощью Python
PDF — один из самых распространённых форматов документов в повседневной работе, но его «таблицы» — это не то же самое, что таблицы в Excel: PDF-файл сам по себе не хранит структурированные табличные данные. Таблица на странице — это лишь визуальный эффект, создаваемый текстом и линиями в соответствии с их позиционными отношениями. Поэтому программное чтение таблиц из PDF по сути сводится к тому, чтобы библиотека проанализировала макет страницы и выявила структуру строк и столбцов.
В этой статье на примере PdfTableExtractor из библиотеки Spire.PDF for Python показано, как обнаруживать таблицы в PDF постранично и считывать каждую ячейку как текст. Весь процесс состоит всего из трёх шагов: загрузить документ → извлечь таблицы постранично → пройти по строкам и столбцам, читая ячейки.
1. Настройка окружения
Установите библиотеку через pip:
pip install Spire.PDF
Если вы только изучаете библиотеку или работаете с небольшими документами, можно также установить бесплатную версию:
pip install Spire.Pdf.Free
Обратите внимание, что бесплатная версия имеет ограничение на количество страниц при загрузке и обработке PDF (не более первых 10 страниц). Документы длиннее 10 страниц перед обработкой необходимо разбить на части либо использовать полную версию из PyPI.
2. Основной код
from spire.pdf import PdfDocument, PdfTableExtractor
# Загрузка PDF-документа
pdf = PdfDocument()
pdf.LoadFromFile("input.pdf")
# Создание объекта PdfTableExtractor
table_extractor = PdfTableExtractor(pdf)
# Извлечение таблиц с каждой страницы
for i in range(pdf.Pages.Count):
tables = table_extractor.ExtractTable(i)
for table_index, table in enumerate(tables):
print(f"Table {table_index + 1} on page {i + 1}:")
for row in range(table.GetRowCount()):
row_data = []
for col in range(table.GetColumnCount()):
text = table.GetText(row, col).replace("\n", " ")
row_data.append(text.strip())
print("\t".join(row_data))
3. Пошаговое объяснение кода
1. Загрузка PDF-документа
pdf = PdfDocument()
pdf.LoadFromFile("input.pdf")
PdfDocument — это объект-входная точка документа. Метод LoadFromFile() загружает PDF, принимая путь к файлу. Путь может быть как относительным, так и абсолютным.
2. Создание извлекателя таблиц
table_extractor = PdfTableExtractor(pdf)
PdfTableExtractor отвечает за постраничный анализ макета и обнаружение структуры таблиц. При создании объекта необходимо передать уже загруженный объект PdfDocument.
3. Постраничное извлечение таблиц
for i in range(pdf.Pages.Count):
tables = table_extractor.ExtractTable(i)
pdf.Pages.Count — общее количество страниц в документе, а ExtractTable(i) возвращает все таблицы, обнаруженные на странице i. Обратите внимание: метод возвращает список — на одной странице может одновременно находиться несколько таблиц; если таблиц на странице нет, возвращается пустой список.
4. Перебор строк и столбцов таблицы
for row in range(table.GetRowCount()):
row_data = []
for col in range(table.GetColumnCount()):
text = table.GetText(row, col).replace("\n", " ")
row_data.append(text.strip())
print("\t".join(row_data))
- GetRowCount() / GetColumnCount() возвращают количество строк и столбцов в таблице;
- GetText(row, col) считывает текст указанной ячейки. В ячейке могут содержаться переводы строк; здесь \n заменяется на пробел, а затем strip() удаляет начальные и конечные пробелы, чтобы в выводе не появлялись лишние пустые строки;
- Наконец, ячейки строки объединяются символом табуляции \t и выводятся, что позволяет легко скопировать результат в Excel или использовать как TSV.
4. Результат выполнения
При запуске приведённого выше кода на PDF, содержащем простую таблицу, вывод будет примерно таким:
Table 1 on page 1:
Name Department Salary
Zhang San Technical Department 12000
Li Si Marketing Department 9800
Wang Wu Finance Department 10500
Каждая строка соответствует строке таблицы, а ячейки разделены табуляцией, поэтому результат можно напрямую вставить в табличный редактор.
5. Продвинутый уровень: сохранение результатов в CSV
Вывод в консоль подходит только для быстрого просмотра. Чтобы сохранить результаты, можно использовать встроенный модуль Python csv — устанавливать дополнительную библиотеку не нужно:
import csv
from spire.pdf import PdfDocument, PdfTableExtractor
pdf = PdfDocument()
pdf.LoadFromFile("input.pdf")
extractor = PdfTableExtractor(pdf)
with open("output.csv«, «w», newline="", encoding="utf-8″) as f:
writer = csv.writer(f)
for i in range(pdf.Pages.Count):
for table in extractor.ExtractTable(i):
for row in range(table.GetRowCount()):
row_data = [
table.GetText(row, col).replace("\n", " ").strip()
for col in range(table.GetColumnCount())
]
writer.writerow(row_data)
pdf.Close()
При записи через csv.writer программа автоматически обрабатывает специальные символы, такие как запятые и кавычки, содержащиеся в ячейках, что надёжнее, чем ручная конкатенация строк.
6. Примечания и ограничения
1. Подходит для таблиц с чёткими границами. PdfTableExtractor опирается на анализ макета страницы. Он хорошо распознаёт таблицы с явными границами и регулярной структурой; для таблиц без видимых границ, с многострочными ячейками или сложной вёрсткой, где заголовки определены нечётко, он может не обнаружить таблицу или построить неполную структуру.
2. Отсканированные документы требуют предварительного OCR. Если PDF представляет собой отсканированное изображение (без текстового слоя), ни один текстовый инструмент не сможет напрямую прочитать содержимое. Сначала нужно применить OCR, чтобы преобразовать изображение в текст. Эта библиотека не предоставляет функций OCR.
3. Ограничение бесплатной версии по страницам. Бесплатная версия может обработать не более первых 10 страниц. При работе с длинными документами рекомендуется добавить в цикл ограничение min(pdf.Pages.Count, 10) или разбить документ постранично.
4. Освобождайте ресурсы после использования. При пакетной обработке большого количества файлов не забывайте в конце вызывать pdf.Close(), чтобы освободить ресурсы.
7. Другие дополнительные библиотеки
Если вы столкнулись со сложными таблицами, которые Spire.PDF не может обработать, можно попробовать следующие библиотеки с открытым исходным кодом:
- pdfplumber : основана на pdfminer.six, предоставляет более детальный доступ к объектам страницы и подходит для работы со сложной вёрсткой;
- camelot : определяет структуру по линиям таблицы и хорошо работает с таблицами с рамками;
- tabula-py : обёртка над Java-версией tabula, её вывод напрямую совместим с pandas DataFrame.
В реальных проектах библиотеки можно комбинировать в зависимости от типа таблиц: обычные таблицы обрабатываются любой библиотекой, а для сложных лучше сначала протестировать на небольшом образце и только затем делать выбор.
8. Итоги
Процесс извлечения таблиц из PDF с помощью Spire.PDF for Python очень прост: загрузить документ → создать PdfTableExtractor → постранично вызывать ExtractTable() → перебрать строки и столбцы, читая ячейки. Такой подход подходит для таблиц с рамками и чёткой структурой, а с помощью модуля csv результаты можно сохранить на диск. Для особых случаев — таблиц без границ и отсканированных документов — потребуются OCR или другие библиотеки как дополнение.
Перевод готов. Технические термины (PdfTableExtractor, LoadFromFile, ExtractTable и т. д.), названия библиотек и код оставлены без изменений; весь пояснительный текст переведён на русский. Если нужно, могу дополнительно сохранить перевод в файл (например, в Markdown или Word).