Spaces:
Sleeping
Sleeping
File size: 6,875 Bytes
5e28e09 78ad12f 5e28e09 5530d18 2b7e158 94ae36a 2b7e158 964278d 2b7e158 94ae36a 2b7e158 94ae36a 2b7e158 94ae36a 5e28e09 9e8b5e4 7bbe6c6 29d547d 5e28e09 32b0a3f 71c6d61 9406f46 71c6d61 2b7e158 9406f46 2b7e158 964278d 5e28e09 94ae36a 9406f46 7569d3f 2b7e158 5e28e09 964278d 2b7e158 964278d 9406f46 7569d3f 5e28e09 94ae36a 9406f46 94ae36a 964278d 32b0a3f 29d547d 964278d 5e28e09 cf5e475 7bbe6c6 9e8b5e4 a67820e ddb1cd6 a67820e 2b7e158 29d547d 2b7e158 29d547d 9e8b5e4 7bbe6c6 964278d 32b0a3f 7bbe6c6 9406f46 32b0a3f 964278d 32b0a3f 9e8b5e4 964278d 7bbe6c6 32b0a3f 964278d 32b0a3f 964278d 9e8b5e4 9406f46 964278d 7bbe6c6 5e28e09 2b7e158 5530d18 29d547d a67820e 2b7e158 5530d18 32b0a3f 5e28e09 7569d3f 9e8b5e4 94ae36a 5e28e09 2b7e158 9e8b5e4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
import os
import shutil
import subprocess
import requests
import gradio as gr
from urllib.parse import urlparse
import time
import re
def sanear_nombre(nombre):
nombre_base = os.path.splitext(nombre)[0]
return re.sub(r"[^\w\-_.]", "_", nombre_base)
def obtener_ruta_segura(base_dir, nombre_archivo):
nombre_base = sanear_nombre(nombre_archivo)
ruta_final = os.path.join(base_dir, nombre_base)
contador = 1
while os.path.exists(ruta_final + ".pdf"):
ruta_final = os.path.join(base_dir, f"{nombre_base}_{contador}")
contador += 1
return ruta_final + ".pdf"
def ejecutar_marker(cmd):
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, timeout=900)
return result
def procesar_pdf(pdf_file=None, url_pdf=None, formatos=[], verbose="auto"):
output_base = "./marker_output"
os.makedirs(output_base, exist_ok=True)
estado = ""
try:
subprocess.run(["marker_single", "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except FileNotFoundError:
yield "Error: el comando 'marker_single' no está disponible.\nVerifica que marker-pdf esté en requirements.txt", None, None
return
if not formatos:
yield "Debes seleccionar al menos un formato de salida.", None, None
return
try:
if url_pdf:
parsed = urlparse(url_pdf)
nombre_pdf = parsed.path.split("/")[-1] or "documento"
ruta_pdf = obtener_ruta_segura(output_base, nombre_pdf)
response = requests.get(url_pdf)
if response.status_code != 200:
yield "No se pudo descargar el PDF desde la URL proporcionada.", None, None
return
with open(ruta_pdf, "wb") as f:
f.write(response.content)
elif pdf_file:
nombre_pdf = pdf_file.name or "documento"
ruta_pdf = obtener_ruta_segura(output_base, nombre_pdf)
shutil.copyfile(pdf_file.name, ruta_pdf)
else:
yield "No se proporcionó ni archivo ni URL.", None, None
return
with open(ruta_pdf, "rb") as f:
if f.read(4) != b"%PDF":
yield "El archivo proporcionado no es un PDF válido.", None, None
return
if os.path.getsize(ruta_pdf) > 3 * 1024 * 1024:
estado += "Aviso: el PDF es grande y puede tardar más de lo normal.\n"
nombre_sin_ext = os.path.splitext(os.path.basename(ruta_pdf))[0]
carpeta_salida = os.path.join(output_base, nombre_sin_ext)
if os.path.exists(carpeta_salida):
shutil.rmtree(carpeta_salida)
os.makedirs(carpeta_salida, exist_ok=True)
for fmt in formatos:
estado += f"\nProcesando formato '{fmt}'..."
yield estado, None, None
# Primer intento sin OCR (si aplica)
if fmt == "md":
cmd = ["marker_single", ruta_pdf, "--output_format", "markdown", "--disable_ocr", "--output_dir", carpeta_salida]
elif fmt == "md + ocr":
cmd = ["marker_single", ruta_pdf, "--output_format", "markdown", "--output_dir", carpeta_salida]
else:
cmd = ["marker_single", ruta_pdf, "--output_format", fmt, "--output_dir", carpeta_salida]
result = ejecutar_marker(cmd)
md_path = os.path.join(carpeta_salida, f"{nombre_sin_ext}.md")
if fmt == "md" and not os.path.exists(md_path):
estado += "\nNo se generó el archivo Markdown en el primer intento."
estado += f"\n\n---\nSalida del comando marker_single:\n{result.stderr.strip()}\n"
estado += "\nReintentando con OCR..."
yield estado, None, None
start_time = time.time()
cmd = ["marker_single", ruta_pdf, "--output_format", "markdown", "--output_dir", carpeta_salida]
result = ejecutar_marker(cmd)
if not os.path.exists(md_path):
estado += "\nEl reintento con OCR también falló."
estado += f"\n\n---\nSalida del reintento:\n{result.stderr.strip()}"
yield estado, None, None
return
elif result.returncode != 0:
estado += f"\n\nError ejecutando marker_single:\n{result.stderr.strip()}"
yield estado, None, None
return
if not os.path.exists(md_path):
estado += "\nNo se generó el archivo Markdown. Puede que el PDF no contenga texto reconocible."
yield estado, None, None
return
with open(md_path, "r", encoding="utf-8") as f:
md_content = f.read()
palabras = len(md_content.split())
caracteres = len(md_content)
figuras = len([f for f in os.listdir(carpeta_salida) if f.lower().endswith(".jpeg")])
tablas = len(os.listdir(os.path.join(carpeta_salida, "tables"))) if os.path.exists(os.path.join(carpeta_salida, "tables")) else 0
tamaño_kb = os.path.getsize(md_path) / 1024
tiempo_total = round(time.time() - start_time, 1)
resumen = f"\n\n---\nResumen del procesamiento:\n"
resumen += f"- Palabras: {palabras}\n"
resumen += f"- Caracteres: {caracteres}\n"
resumen += f"- Tamaño Markdown: {tamaño_kb:.2f} KB\n"
resumen += f"- Imágenes extraídas: {figuras}\n"
resumen += f"- Tablas detectadas: {tablas}\n"
resumen += f"- Tiempo total: {tiempo_total} s"
zip_path = os.path.join(output_base, f"{nombre_sin_ext}.zip")
shutil.make_archive(base_name=zip_path.replace(".zip", ""), format="zip", root_dir=carpeta_salida)
estado += "\n\nProcesamiento finalizado correctamente."
yield estado + resumen, gr.update(value=md_path, visible=True), gr.update(value=zip_path, visible=True)
except Exception as e:
yield f"Error general inesperado: {str(e)}", None, None
demo = gr.Interface(
fn=procesar_pdf,
inputs=[
gr.File(label="Sube un PDF (opcional)", file_types=[".pdf"]),
gr.Textbox(label="O introduce una URL directa", placeholder="https://arxiv.org/pdf/..."),
gr.CheckboxGroup(
choices=["md", "md + ocr", "html", "json"],
value=["md"],
label="Formatos de salida (elige al menos uno)"
)
],
outputs=[
gr.Textbox(label="Estado del procesamiento", lines=12),
gr.File(label="Descargar Markdown (.md)", visible=False),
gr.File(label="Descargar ZIP completo", visible=False)
],
title="Marker PDF",
description="Convierte artículos científicos en Markdown, HTML o JSON. Reintenta automáticamente con OCR si es necesario.",
flagging_mode="never"
)
if __name__ == "__main__":
demo.launch() |