Skip to content

Biblioteca PDF para Python: PDF Oxide em dez linhas

PDF Oxide é a biblioteca PDF mais rápida para Python: 0,8 ms em média por página, 5 vezes mais rápida que o PyMuPDF e 100 % de sucesso em 3 830 PDFs testados. Uma única biblioteca para extrair, criar e editar — licença MIT, núcleo em Rust e sem dependências de sistema.

Instalação

pip install pdf_oxide

Requisitos: Python 3.8 ou mais recente. Wheels pré-compilados estão disponíveis para Linux, macOS e Windows em x86_64 e ARM64. Você não precisa de compilador nem de pacotes do sistema.

Abrindo um PDF

Use PdfDocument para abrir e inspecionar qualquer arquivo PDF.

from pdf_oxide import PdfDocument

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

API de páginas

Desde a v0.3.34 PdfDocument é iterável e indexável, retornando objetos PdfPage com propriedades preguiçosas.

from pdf_oxide import PdfDocument

with PdfDocument("paper.pdf") as doc:
    for page in doc:            # len(doc), doc[i], doc[-1] funcionam
        text = page.text        # preguiçoso — calculado no acesso
        md = page.markdown(detect_headings=True)
        for table in page.tables:
            for row in table["rows"]:
                print([cell["text"] for cell in row["cells"]])

Propriedades de página (todas preguiçosas): text, chars, words, lines, spans, tables, images, paths, annotations, width, height, bbox. Métodos: markdown(), plain_text(), html(), render(), search(), region(x, y, w, h).

A classe de página do editor foi renomeada para EditorPage na v0.3.34 para evitar colisão com PdfPage.

Extração de texto

Uma página

Extraia texto puro de uma página pelo índice baseado em zero.

from pdf_oxide import PdfDocument

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

Todas as páginas

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)

Extração caractere a caractere

extract_chars() retorna uma lista de objetos TextChar com posição exata e metadados de fonte para cada caractere da página.

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}")

Cada TextChar traz os seguintes campos:

Campo Tipo Descrição
char str O caractere Unicode
x float Posição horizontal em pontos
y float Posição vertical em pontos
font_size float Tamanho da fonte em pontos
font_name str Nome PostScript da fonte
bbox tuple[float, 4] Caixa delimitadora (x0, y0, x1, y1)

Spans de texto

extract_spans() agrupa caracteres consecutivos que compartilham a mesma fonte e tamanho em spans, entregando texto estruturado com metadados de fonte.

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}")

Conversão para Markdown

Converta uma página de PDF para Markdown, com detecção opcional de títulos.

from pdf_oxide import PdfDocument

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

Conversão para HTML

Converta uma página de PDF para HTML.

from pdf_oxide import PdfDocument

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

Extração de imagens

extract_images() devolve uma lista de objetos ImageInfo para cada imagem embutida na página, incluindo imagens referenciadas em content streams e Form XObjects aninhados.

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"])

Cada dict retornado por extract_image_bytes() tem as seguintes chaves:

Chave Tipo Descrição
width int Largura em pixels
height int Altura em pixels
data bytes Dados brutos da imagem
format str Formato (ex.: png, jpeg)

Abrindo a partir de bytes

Abra um PDF a partir de bytes em memória — útil ao baixar do S3, de HTTP ou de bancos de dados:

from pdf_oxide import PdfDocument

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

# Também aceita senha:
doc = PdfDocument.from_bytes(pdf_bytes, password="secret")

Para a API de construtor:

from pdf_oxide import Pdf

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

PDFs com senha

Passe password= no construtor para abrir documentos criptografados.

from pdf_oxide import PdfDocument

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

Você também pode usar doc.authenticate(password) depois de abrir o arquivo.

Criação de PDFs

A classe Pdf oferece métodos de fábrica para criar PDFs a partir de vários formatos de origem.

A partir de Markdown

from pdf_oxide import Pdf

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

A partir de HTML

from pdf_oxide import Pdf

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

A partir de texto puro

from pdf_oxide import Pdf

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

A partir de imagens

from pdf_oxide import Pdf

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

Busca

Busque texto em todo o documento ou em uma página específica.

from pdf_oxide import PdfDocument

doc = PdfDocument("manual.pdf")

# Buscar em todas as páginas
results = doc.search("configuration")
for r in results:
    print(f"Page {r.page}: '{r.text}' at ({r.x:.0f}, {r.y:.0f})")

# Buscar em uma única página
page_results = doc.search_page(0, "configuration")

Tratamento de erros

PDF Oxide lança PdfError para falhas específicas de PDF e exceções padrão do Python para problemas de I/O.

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")

Próximos passos