Skip to content

PDF-бібліотека для Python: PDF Oxide у десять рядків

PDF Oxide — найшвидша PDF-бібліотека для Python. Видобування тексту триває в середньому 0,8 мс на сторінку — у 5 разів швидше за PyMuPDF, при 100 % успішній обробці 3 830 тестових PDF. Одна бібліотека покриває видобування, створення й редагування. Ліцензія MIT, ядро на Rust, без системних залежностей.

Встановлення

pip install pdf_oxide

Вимоги: Python 3.8 або новіше. Готові wheel-пакети доступні для Linux, macOS і Windows на x86_64 та ARM64. Компілятор і системні пакунки не потрібні.

Відкриття PDF

Скористайтеся PdfDocument, щоб відкрити будь-який PDF і подивитися його властивості.

from pdf_oxide import PdfDocument

doc = PdfDocument("research-paper.pdf")
print(f"Pages: {doc.page_count()}")
print(f"PDF version: {doc.version()}")

API сторінок

З версії v0.3.34 PdfDocument підтримує ітерацію й індексацію та повертає об’єкти PdfPage з лінивими властивостями.

from pdf_oxide import PdfDocument

with PdfDocument("paper.pdf") as doc:
    for page in doc:            # len(doc), doc[i], doc[-1] працюють
        text = page.text        # ліниве — обчислюється при зверненні
        md = page.markdown(detect_headings=True)
        for table in page.tables:
            for row in table["rows"]:
                print([cell["text"] for cell in row["cells"]])

Властивості сторінки (усі ліниві): text, chars, words, lines, spans, tables, images, paths, annotations, width, height, bbox. Методи: markdown(), plain_text(), html(), render(), search(), region(x, y, w, h).

У v0.3.34 клас сторінки редактора перейменовано на EditorPage, щоб уникнути конфлікту з PdfPage.

Видобування тексту

Одна сторінка

Видобудьте звичайний текст сторінки за її індексом (з нуля).

from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
print(text)

Усі сторінки

from pdf_oxide import PdfDocument

doc = PdfDocument("book.pdf")
for i in range(doc.page_count()):
    text = doc.extract_text(i)
    print(f"--- Page {i + 1} ---")
    print(text)

Посимвольне видобування

extract_chars() повертає список об’єктів TextChar із точним положенням і метаданими шрифту для кожного символу на сторінці.

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
chars = doc.extract_chars(0)

for ch in chars[:10]:
    print(f"'{ch.char}' at ({ch.x:.1f}, {ch.y:.1f}) "
          f"size={ch.font_size:.1f} font={ch.font_name} "
          f"bbox={ch.bbox}")

Кожен TextChar має такі поля:

Поле Тип Опис
char str Символ Unicode
x float Горизонтальна координата у пунктах
y float Вертикальна координата у пунктах
font_size float Розмір шрифту у пунктах
font_name str PostScript-назва шрифту
bbox tuple[float, 4] Обмежувальний прямокутник (x0, y0, x1, y1)

Текстові спани

extract_spans() групує послідовні символи з однаковим шрифтом і розміром у спани, повертаючи структурований текст із метаданими шрифту.

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
spans = doc.extract_spans(0)

for span in spans:
    print(f"'{span.text}' font={span.font_name} size={span.font_size}")

Конвертація у Markdown

Перетворіть сторінку PDF у Markdown із необов’язковим розпізнаванням заголовків.

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
md = doc.to_markdown(0, detect_headings=True)
print(md)

Конвертація у HTML

Перетворіть сторінку PDF у HTML.

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
html = doc.to_html(0)
print(html)

Видобування зображень

extract_images() повертає список об’єктів ImageInfo для кожного зображення, вбудованого у сторінку, включно з картинками у content stream і вкладених Form XObject.

from pdf_oxide import PdfDocument

doc = PdfDocument("brochure.pdf")
images = doc.extract_image_bytes(0)

for i, img in enumerate(images):
    print(f"Image {i}: {img['width']}x{img['height']} "
          f"({len(img['data'])} bytes)")
    with open(f"image_{i}.{img['format']}", "wb") as f:
        f.write(img["data"])

Кожен словник, що повертає extract_image_bytes(), містить такі ключі:

Ключ Тип Опис
width int Ширина зображення у пікселях
height int Висота зображення у пікселях
data bytes Сирі байти зображення
format str Формат (напр., png, jpeg)

Відкриття з байтів

Відкрийте PDF із байтів у пам’яті — зручно для завантаженого з S3, HTTP або бази даних:

from pdf_oxide import PdfDocument

doc = PdfDocument.from_bytes(pdf_bytes)
text = doc.extract_text(0)

# Пароль теж підтримується:
doc = PdfDocument.from_bytes(pdf_bytes, password="secret")

Для API-будівника:

from pdf_oxide import Pdf

pdf = Pdf.from_bytes(existing_pdf_bytes)
pdf.save("modified.pdf")

PDF із паролем

Щоб відкрити зашифрований документ, передайте password= до конструктора.

from pdf_oxide import PdfDocument

doc = PdfDocument("confidential.pdf", password="secret")
text = doc.extract_text(0)
print(text)

Також можна викликати doc.authenticate(password) уже після відкриття.

Створення PDF

Клас Pdf надає фабричні методи для створення PDF із різних вхідних форматів.

Із Markdown

from pdf_oxide import Pdf

pdf = Pdf.from_markdown("# Hello World\n\nThis is a PDF.")
pdf.save("output.pdf")

Із HTML

from pdf_oxide import Pdf

pdf = Pdf.from_html("<h1>Invoice</h1><p>Amount due: $42.00</p>")
pdf.save("invoice.pdf")

З простого тексту

from pdf_oxide import Pdf

pdf = Pdf.from_text("Plain text document.\n\nSecond paragraph.")
pdf.save("notes.pdf")

Із зображень

from pdf_oxide import Pdf

pdf = Pdf.from_image("scan.jpg")
pdf.save("scan.pdf")

Пошук

Шукайте текст по всьому документу або в межах однієї сторінки.

from pdf_oxide import PdfDocument

doc = PdfDocument("manual.pdf")

# Пошук по всіх сторінках
results = doc.search("configuration")
for r in results:
    print(f"Page {r.page}: '{r.text}' at ({r.x:.0f}, {r.y:.0f})")

# Пошук на одній сторінці
page_results = doc.search_page(0, "configuration")

Обробка помилок

PDF Oxide кидає PdfError для специфічних для PDF збоїв і стандартні винятки Python — для проблем вводу/виводу.

from pdf_oxide import PdfDocument, PdfError

try:
    doc = PdfDocument("document.pdf")
    text = doc.extract_text(0)
except PdfError as e:
    print(f"PDF error: {e}")
except FileNotFoundError:
    print("File not found")

Наступні кроки