0Pricing
AI Agents · Lección

Análisis de PDF con PyMuPDF y pdfplumber

Extraiga texto, tablas y metadatos de archivos PDF mediante programación.

Análisis de PDF con PyMuPDF y pdfplumber es una lección gratuita de AI Agents en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Agents, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Agents incluye 4 lecciones en total.

Por qué analizar archivos PDF no es sencillo

Los PDF son un formato de presentación, no un formato de datos. El texto se almacena como glifos posicionados, no como párrafos lógicos. Extraer texto con significado requiere comprender el diseño, el orden de lectura y las propiedades de las fuentes, además de gestionar casos límite como diseños con varias columnas, encabezados y pies de página e imágenes incrustadas.

Dos bibliotecas son las más utilizadas: PyMuPDF (velocidad) y pdfplumber (extracción de tablas).

Conceptos básicos de PyMuPDF

PyMuPDF (que se importa como fitz) es la biblioteca de Python más rápida para trabajar con PDF. Permite extraer texto, metadatos e imágenes, además de renderizar documentos. Instálela con pip install pymupdf.

import fitz  # PyMuPDF

# Open a PDF
doc = fitz.open('document.pdf')

print(f'Pages: {len(doc)}')
print(f'Metadata: {doc.metadata}')

# Extract text from all pages
full_text = ''
for page_num in range(len(doc)):
    page = doc[page_num]
    text = page.get_text()  # plain text extraction
    full_text += f'--- Page {page_num + 1} ---\n{text}\n'

doc.close()
print(full_text[:500])

Modos de extracción de texto de PyMuPDF

page.get_text() admite distintos formatos de salida. Utilice 'text' para texto sin formato, 'blocks' para bloques de texto con cuadros delimitadores y 'dict' para una salida estructurada enriquecida que incluya los nombres y tamaños de las fuentes.

import fitz

doc = fitz.open('report.pdf')
page = doc[0]

# Mode 1: plain text
plain = page.get_text('text')

# Mode 2: blocks (each block has bbox + text)
blocks = page.get_text('blocks')
for block in blocks:
    x0, y0, x1, y1, text, block_no, block_type = block
    if block_type == 0:  # text block (1 = image)
        print(f'Block at ({x0:.0f},{y0:.0f}): {text[:80]}')

# Mode 3: dict (full detail including font info)
page_dict = page.get_text('dict')
for block in page_dict['blocks']:
    if block.get('type') == 0:  # text
        for line in block['lines']:
            for span in line['spans']:
                print(f"Font: {span['font']}, Size: {span['size']:.1f}, Text: {span['text']}")

doc.close()

Extracción de metadatos de las páginas

Los metadatos de las páginas ayudan a los agentes a comprender la estructura del documento: número de páginas, título del documento, autor, fecha de creación y dimensiones de las páginas. PyMuPDF proporciona toda esta información.

import fitz

def extract_pdf_metadata(filepath):
    doc = fitz.open(filepath)
    meta = doc.metadata
    info = {
        'title':    meta.get('title', 'Unknown'),
        'author':   meta.get('author', 'Unknown'),
        'subject':  meta.get('subject', ''),
        'creator':  meta.get('creator', ''),
        'created':  meta.get('creationDate', ''),
        'modified': meta.get('modDate', ''),
        'pages':    len(doc),
        'page_size': {
            'width':  doc[0].rect.width,
            'height': doc[0].rect.height
        }
    }
    doc.close()
    return info

meta = extract_pdf_metadata('contract.pdf')
print(f"Title: {meta['title']}, Pages: {meta['pages']}")

pdfplumber para extraer tablas

pdfplumber destaca en la extracción de tablas de archivos PDF. Utiliza análisis geométrico para detectar los límites de las celdas, incluso en PDF que no contienen un marcado explícito de tablas.

Instálelo con pip install pdfplumber.

import pdfplumber

with pdfplumber.open('financial_report.pdf') as pdf:
    for page_num, page in enumerate(pdf.pages):
        tables = page.extract_tables()
        for table_idx, table in enumerate(tables):
            print(f'Page {page_num+1}, Table {table_idx+1}:')
            # table is a list of rows; each row is a list of cell strings
            headers = table[0]
            for row in table[1:]:
                row_dict = dict(zip(headers, row))
                print(row_dict)

Configuración de tablas en pdfplumber

La extracción de tablas de pdfplumber se puede ajustar mediante opciones para gestionar distintos estilos de tabla: líneas explícitas, columnas separadas por espacios o diseños mixtos.

import pdfplumber

# Custom table settings for borderless tables
table_settings = {
    'vertical_strategy':   'text',   # 'lines', 'lines_strict', 'text', 'explicit'
    'horizontal_strategy': 'text',
    'snap_tolerance':       5,
    'join_tolerance':       3,
    'edge_min_length':     50,
    'min_words_vertical':   3,
    'min_words_horizontal': 1
}

with pdfplumber.open('nolines_table.pdf') as pdf:
    page = pdf.pages[0]
    table = page.extract_table(table_settings)
    if table:
        import csv
        import io
        output = io.StringIO()
        writer = csv.writer(output)
        writer.writerows(table)
        csv_string = output.getvalue()
        print(csv_string[:300])

Gestión de diseños con varias columnas

Los artículos académicos y los periódicos utilizan diseños con varias columnas. La extracción de texto ingenua lee de izquierda a derecha atravesando las columnas, lo que produce texto ilegible. Corrija este problema ordenando primero los bloques de texto por columna.

import fitz

def extract_multicolumn_text(page, n_columns=2):
    page_width = page.rect.width
    col_width = page_width / n_columns

    blocks = page.get_text('blocks')
    # Filter text blocks only
    text_blocks = [b for b in blocks if b[6] == 0]

    # Assign each block to a column based on x position
    columns = [[] for _ in range(n_columns)]
    for block in text_blocks:
        x0 = block[0]
        col_idx = min(int(x0 / col_width), n_columns - 1)
        columns[col_idx].append(block)

    # Sort each column by vertical position
    for col in columns:
        col.sort(key=lambda b: b[1])  # sort by y0

    # Read columns left to right
    full_text = ''
    for col in columns:
        for block in col:
            full_text += block[4] + '\n'
    return full_text

Filtrado de encabezados y pies de página

Los encabezados y pies de página de los PDF se repiten en todas las páginas y contaminan el texto extraído. Identifíquelos por su posición vertical (el 10 % superior o inferior de la página) y exclúyalos de la extracción de contenido.

import fitz

def extract_without_headers_footers(page, margin_ratio=0.08):
    page_height = page.rect.height
    top_margin = page_height * margin_ratio
    bottom_margin = page_height * (1 - margin_ratio)

    blocks = page.get_text('blocks')
    content_blocks = []

    for block in blocks:
        x0, y0, x1, y1, text, block_no, block_type = block
        if block_type != 0:
            continue  # skip image blocks
        # Skip blocks in header or footer zone
        if y0 < top_margin or y1 > bottom_margin:
            continue
        content_blocks.append(text)

    return '\n'.join(content_blocks)

Segmentación de texto PDF para agentes

Los PDF largos deben dividirse en fragmentos para generar embeddings y realizar búsquedas. Divida el contenido en límites naturales: párrafos, secciones o páginas. Incluya solapamiento entre los fragmentos para evitar cortar el contexto a mitad de una oración.

import fitz

def pdf_to_chunks(filepath, chunk_size=1000, overlap=200):
    doc = fitz.open(filepath)
    chunks = []

    for page_num in range(len(doc)):
        page = doc[page_num]
        page_text = page.get_text()

        # Split into chunks with overlap
        start = 0
        while start < len(page_text):
            end = start + chunk_size
            chunk = page_text[start:end]
            chunks.append({
                'text': chunk,
                'page': page_num + 1,
                'char_start': start,
                'source': filepath
            })
            start += chunk_size - overlap  # overlap

    doc.close()
    return chunks

chunks = pdf_to_chunks('research_paper.pdf')
print(f'Total chunks: {len(chunks)}')
print(f'Sample: {chunks[0]["text"][:200]}')

Combinación de PyMuPDF y pdfplumber

Use PyMuPDF para extraer texto (es más rápido) y pdfplumber para detectar tablas (es más preciso). Un extractor combinado ejecuta ambas bibliotecas en cada página y devuelve contenido estructurado, con el texto y las tablas separados.

import fitz
import pdfplumber

def full_pdf_extract(filepath):
    result = {'text_by_page': [], 'tables': []}

    # Text extraction with PyMuPDF
    doc = fitz.open(filepath)
    for i in range(len(doc)):
        text = extract_without_headers_footers(doc[i])
        result['text_by_page'].append({'page': i + 1, 'text': text})
    doc.close()

    # Table extraction with pdfplumber
    with pdfplumber.open(filepath) as pdf:
        for page_num, page in enumerate(pdf.pages):
            tables = page.extract_tables()
            for t in tables:
                result['tables'].append({
                    'page': page_num + 1,
                    'headers': t[0] if t else [],
                    'rows': t[1:] if t and len(t) > 1 else []
                })

    return result

Guardado del texto extraído en archivos

Después de extraer texto de los PDF, guárdelo en un formato que los agentes posteriores puedan procesar. Los archivos de texto sin formato funcionan bien en los pipelines de embeddings; JSON conserva la estructura de las páginas para realizar el seguimiento de las citas.

import json, os

class FakePage:
    def __init__(self, text): self.text = text
    def get_text(self): return self.text

class FakeDoc(list):
    def close(self): pass

def fitz_open(path):
    return FakeDoc([FakePage('Page 1 text'), FakePage('Page 2 text')])

def pdf_to_text_file(pdf_path, output_dir):
    doc = fitz_open(pdf_path)
    base = os.path.splitext(os.path.basename(pdf_path))[0]
    txt_path = os.path.join(output_dir, base + '.txt')
    with open(txt_path, 'w', encoding='utf-8') as f:
        for i, page in enumerate(doc):
            f.write(f'--- Page {i+1} ---\n{page.get_text()}\n')
    json_path = os.path.join(output_dir, base + '.json')
    pages = [{'page': i+1, 'text': p.get_text()} for i, p in enumerate(doc)]
    with open(json_path, 'w') as f:
        json.dump({'source': pdf_path, 'pages': pages}, f, indent=2)
    doc.close()
    print(f'Saved: {txt_path} and {json_path}')
    return txt_path, json_path

pdf_to_text_file('sample.pdf', '.')

Comprobación de conocimientos

¿Qué biblioteca de Python es la más adecuada para extraer tablas de archivos PDF?

Resumen: análisis de PDF con PyMuPDF y pdfplumber

PyMuPDF (fitz) es la opción rápida para extraer texto y metadatos, así como para gestionar diseños de varias columnas. pdfplumber destaca en la extracción de tablas gracias a sus estrategias geométricas configurables.

Técnicas clave: use get_text('blocks') para extraer contenido teniendo en cuenta su posición, filtre los encabezados y pies de página según su posición vertical, gestione los diseños de varias columnas ordenando los bloques por columna y divida el texto en fragmentos con solapamiento para los sistemas de recuperación de agentes. Combine ambas bibliotecas para obtener los mejores resultados.

Preguntas frecuentes

¿La lección «Análisis de PDF con PyMuPDF y pdfplumber» es gratis?

Sí — el texto completo de «Análisis de PDF con PyMuPDF y pdfplumber» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Agents, actualiza a CoddyKit PRO. El curso de AI Agents incluye 4 lecciones en total.

¿Qué aprenderé en «Análisis de PDF con PyMuPDF y pdfplumber»?

Extraiga texto, tablas y metadatos de archivos PDF mediante programación. Practicas AI Agents con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar AI Agents?

No se requiere experiencia previa. AI Agents en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Análisis de PDF con PyMuPDF y pdfplumber»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de AI Agents?

Sí. Cada lección de AI Agents incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Análisis de PDF con PyMuPDF y pdfplumber
  2. OCR para documentos escaneados
  3. Agentes de preguntas y respuestas sobre varios documentos
  4. Clasificación y enrutamiento de documentos
← Volver a AI Agents