Extraer texto de archivos PDF con Python es una tarea común en automatización, análisis documental, búsqueda interna y preparación de datos. Sin embargo, un PDF no siempre contiene texto de la misma manera. Algunos documentos guardan caracteres seleccionables, otros contienen tablas complejas y muchos son simplemente imágenes escaneadas. Por eso la herramienta adecuada depende del tipo de archivo.
Antes de empezar, conviene conocer el manejo de rutas con pathlib, las excepciones en Python, el procesamiento de archivos CSV y la creación de funciones reutilizables. También debes respetar la privacidad, los derechos de acceso y las restricciones legales de los documentos.
Elegir una biblioteca
Para texto normal, pypdf es una opción moderna y sencilla. Para diseños complejos y tablas, pdfplumber ofrece más control sobre posiciones y palabras. La documentación oficial de pypdf explica sus capacidades y limitaciones. El repositorio oficial de pdfplumber incluye ejemplos para texto, tablas y coordenadas.
Instalar las dependencias
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux o macOS
source .venv/bin/activate
python -m pip install pypdf pdfplumberUtiliza un entorno virtual para evitar conflictos y guarda las versiones del proyecto en requirements.txt.
Extraer texto con pypdf
from pathlib import Path
from pypdf import PdfReader
ruta = Path("documento.pdf")
lector = PdfReader(ruta)
for numero, pagina in enumerate(lector.pages, start=1):
texto = pagina.extract_text() or ""
print(f"--- Página {numero} ---")
print(texto)extract_text() puede devolver None cuando no encuentra contenido textual. Por eso se utiliza or "".
Guardar todo el texto en un archivo
partes = []
for pagina in lector.pages:
partes.append(pagina.extract_text() or "")
texto_completo = "\n\n".join(partes)
Path("documento.txt").write_text(texto_completo, encoding="utf-8")Separar páginas con líneas vacías mejora la lectura. Para auditorías, puedes incluir marcadores como [PÁGINA 3].
Crear una función reutilizable
def extraer_texto_pdf(ruta_pdf: Path) -> str:
lector = PdfReader(ruta_pdf)
paginas = []
for indice, pagina in enumerate(lector.pages, start=1):
texto = pagina.extract_text() or ""
paginas.append(f"[PÁGINA {indice}]\n{texto}")
return "\n\n".join(paginas)Esta función facilita las pruebas y permite usar el resultado en una API, un buscador o un proceso de clasificación.
Procesar una carpeta completa
entrada = Path("pdfs")
salida = Path("textos")
salida.mkdir(exist_ok=True)
for pdf in entrada.glob("*.pdf"):
try:
texto = extraer_texto_pdf(pdf)
destino = salida / f"{pdf.stem}.txt"
destino.write_text(texto, encoding="utf-8")
except Exception as error:
print(f"Error en {pdf.name}: {error}")En producción, reemplaza print() por logging y registra qué documentos fallaron.
Manejar PDF protegidos
lector = PdfReader("protegido.pdf")
if lector.is_encrypted:
resultado = lector.decrypt("contraseña")
if resultado == 0:
raise ValueError("No se pudo desbloquear el PDF")No intentes evadir protecciones ni proceses documentos sin autorización. La contraseña debe recibirse desde una fuente segura, no escribirse en el código.
Extraer texto con pdfplumber
import pdfplumber
with pdfplumber.open("documento.pdf") as pdf:
for pagina in pdf.pages:
texto = pagina.extract_text() or ""
print(texto)pdfplumber resulta especialmente útil cuando necesitas palabras con coordenadas:
with pdfplumber.open("documento.pdf") as pdf:
palabras = pdf.pages[0].extract_words()
for palabra in palabras[:10]:
print(palabra)Cada elemento puede incluir texto y posiciones como x0, x1, top y bottom.
Extraer tablas
with pdfplumber.open("informe.pdf") as pdf:
tabla = pdf.pages[0].extract_table()
for fila in tabla or []:
print(fila)Las tablas en PDF no son verdaderas hojas de cálculo. Muchas veces solo son palabras dibujadas en posiciones específicas. La extracción puede requerir ajustes en líneas verticales, horizontales y tolerancias.
Convertir una tabla a CSV
import csv
if tabla:
with open("tabla.csv", "w", newline="", encoding="utf-8") as archivo:
escritor = csv.writer(archivo)
escritor.writerows(tabla)Después revisa encabezados, columnas desplazadas y celdas combinadas. No asumas que el resultado es correcto solo porque se generó un archivo.
PDF escaneados y OCR
Si no puedes seleccionar el texto en un visor, probablemente el PDF contiene imágenes. En ese caso necesitas OCR. Una estrategia común es convertir páginas a imágenes y usar Tesseract u otro motor. El OCR introduce errores, especialmente con baja resolución, columnas, tablas, fuentes pequeñas y documentos inclinados.
Antes de añadir OCR, comprueba si extract_text() devuelve muy poco contenido:
texto = extraer_texto_pdf(Path("documento.pdf"))
if len(texto.strip()) < 50:
print("El documento puede necesitar OCR")Este umbral es solo una señal; una página legítima también puede tener poco texto.
Limpiar el texto extraído
import re
def limpiar_texto(texto: str) -> str:
texto = texto.replace("\u00ad", "")
texto = re.sub(r"-\n(?=\w)", "", texto)
texto = re.sub(r"[ \t]+", " ", texto)
texto = re.sub(r"\n{3,}", "\n\n", texto)
return texto.strip()Eliminar guiones de final de línea puede unir palabras correctamente, pero también puede alterar términos que realmente llevan guion. Conserva una copia del texto original.
Extraer únicamente algunas páginas
lector = PdfReader("libro.pdf")
inicio = 10
fin = 20
for pagina in lector.pages[inicio:fin]:
print(pagina.extract_text() or "")Los índices empiezan en cero. La página visible 11 suele corresponder al índice 10, aunque portadas y numeración impresa pueden causar diferencias.
Validar archivos antes de procesar
def validar_pdf(ruta: Path, max_mb=50):
if ruta.suffix.lower() != ".pdf":
raise ValueError("Extensión no permitida")
if not ruta.is_file():
raise FileNotFoundError(ruta)
if ruta.stat().st_size > max_mb * 1024 * 1024:
raise ValueError("Archivo demasiado grande")Los límites protegen al servidor contra archivos inesperadamente grandes. También puedes restringir el número de páginas.
Registrar metadatos
lector = PdfReader("documento.pdf")
print(lector.metadata)
print("Páginas:", len(lector.pages))Los metadatos pueden incluir título, autor o fecha, pero no siempre son correctos ni confiables.
Procesamiento paralelo
Para muchos documentos, procesa varios archivos en paralelo con límites. No abras cientos al mismo tiempo. Empieza con pocos trabajadores y mide memoria, disco y CPU. Para OCR, la carga suele ser mucho mayor que para extracción textual.
Errores frecuentes
Los fallos más comunes son asumir que todo PDF contiene texto seleccionable, ignorar documentos protegidos, perder la separación entre páginas, confiar ciegamente en tablas extraídas, sobrescribir resultados y procesar archivos enormes sin límites. También debes manejar documentos corruptos y fuentes con codificaciones especiales.
Conclusión
pypdf es adecuado para extraer texto y metadatos de documentos convencionales, mientras que pdfplumber ofrece más control para tablas y posiciones. Los PDF escaneados requieren OCR. Un proceso confiable valida tamaño, permisos y número de páginas, conserva el texto original, registra errores y revisa la calidad del resultado. Con estas precauciones puedes convertir colecciones de PDF en texto buscable, CSV o datos preparados para análisis.






