Skip to content

Biblioteca PDF para Python: PDF Oxide en diez líneas

PDF Oxide es la biblioteca PDF más rápida para Python: 0,8 ms promedio por página, 5 veces más rápida que PyMuPDF y 100 % de éxito sobre 3 830 PDFs de prueba. Una sola biblioteca para extraer, crear y editar — licencia MIT, núcleo en Rust, sin dependencias del sistema.

Instalación

pip install pdf_oxide

Requisitos: Python 3.8 o superior. Hay wheels precompilados para Linux, macOS y Windows en x86_64 y ARM64. No necesitas compilador ni paquetes del sistema.

Abrir un PDF

Usa PdfDocument para abrir e inspeccionar cualquier archivo 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 v0.3.34 PdfDocument es iterable e indexable, y devuelve objetos PdfPage con propiedades perezosas.

from pdf_oxide import PdfDocument

with PdfDocument("paper.pdf") as doc:
    for page in doc:            # len(doc), doc[i], doc[-1] funcionan
        text = page.text        # perezoso — se calcula al acceder
        md = page.markdown(detect_headings=True)
        for table in page.tables:
            for row in table["rows"]:
                print([cell["text"] for cell in row["cells"]])

Propiedades de página (todas perezosas): 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).

La clase de página del editor pasó a llamarse EditorPage en v0.3.34 para evitar colisiones con PdfPage.

Extracción de texto

Una sola página

Extrae texto plano de una página por su índice (empieza en cero).

from pdf_oxide import PdfDocument

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

Todas las 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)

Extracción por carácter

extract_chars() devuelve una lista de objetos TextChar con posición exacta y metadatos de fuente para cada carácter de la 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 incluye estos campos:

Campo Tipo Descripción
char str El carácter Unicode
x float Posición horizontal en puntos
y float Posición vertical en puntos
font_size float Tamaño de fuente en puntos
font_name str Nombre PostScript de la fuente
bbox tuple[float, 4] Caja delimitadora (x0, y0, x1, y1)

Spans de texto

extract_spans() agrupa caracteres consecutivos con la misma fuente y tamaño en spans, devolviendo texto estructurado con metadatos de fuente.

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

Conversión a Markdown

Convierte una página de PDF a Markdown, con detección opcional de encabezados.

from pdf_oxide import PdfDocument

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

Conversión a HTML

Convierte una página de PDF a HTML.

from pdf_oxide import PdfDocument

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

Extracción de imágenes

extract_images() devuelve una lista de objetos ImageInfo con cada imagen embebida en la página, incluyendo imágenes dentro de content streams y Form XObjects anidados.

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 devuelto por extract_image_bytes() tiene estas claves:

Clave Tipo Descripción
width int Ancho en píxeles
height int Alto en píxeles
data bytes Datos crudos de la imagen
format str Formato (p. ej. png, jpeg)

Abrir desde bytes

Abre un PDF desde bytes en memoria — útil al descargar desde S3, HTTP o bases de datos:

from pdf_oxide import PdfDocument

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

# También acepta contraseña:
doc = PdfDocument.from_bytes(pdf_bytes, password="secret")

Para la API de constructor:

from pdf_oxide import Pdf

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

PDFs con contraseña

Pasa password= al constructor para abrir documentos cifrados.

from pdf_oxide import PdfDocument

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

También puedes usar doc.authenticate(password) tras abrirlo.

Creación de PDFs

La clase Pdf ofrece métodos de fábrica para crear PDFs desde distintos formatos de origen.

Desde Markdown

from pdf_oxide import Pdf

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

Desde HTML

from pdf_oxide import Pdf

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

Desde texto plano

from pdf_oxide import Pdf

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

Desde imágenes

from pdf_oxide import Pdf

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

Búsqueda

Busca texto en todo el documento o en una página concreta.

from pdf_oxide import PdfDocument

doc = PdfDocument("manual.pdf")

# Buscar en todas las 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 en una sola página
page_results = doc.search_page(0, "configuration")

Manejo de errores

PDF Oxide lanza PdfError para errores específicos del PDF y excepciones estándar de 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 pasos