From aabe4d168c998f0fa00975c0b3a4f5d43c1b0dc8 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Thu, 4 Jun 2026 12:14:48 +0200 Subject: [PATCH] feat(notebook): sostituisce visualizzazione layout con download ZIP output MinerU La cella finale ora crea uno ZIP della cartella di output (auto o hybrid_auto) e lo scarica automaticamente su Colab, pronto per essere decompresso in sources/. Co-Authored-By: Claude Sonnet 4.6 --- mineru.ipynb | 196 ++++++++++++++++++--------------------------------- 1 file changed, 68 insertions(+), 128 deletions(-) diff --git a/mineru.ipynb b/mineru.ipynb index b7a9388..55a393a 100644 --- a/mineru.ipynb +++ b/mineru.ipynb @@ -46,7 +46,9 @@ "metadata": { "id": "Rw-hwakFwaeY" }, - "source": "### Install via pip" + "source": [ + "### Install via pip" + ] }, { "cell_type": "code", @@ -60,7 +62,10 @@ "outputId": "a4c96ba2-6dea-4ef0-aac7-955dbfac0598" }, "outputs": [], - "source": "!pip install --upgrade pip\n!pip install \"mineru[all]>=3.1.3\"" + "source": [ + "!pip install --upgrade pip\n", + "!pip install \"mineru[all]>=3.1.3\"" + ] }, { "cell_type": "markdown", @@ -126,7 +131,28 @@ "metadata": { "id": "Hyoz1B-tPXcM" }, - "source": "#### **Converti un singolo PDF**\n\nSu Google Colab il file system è temporaneo: ogni volta che avvii una nuova sessione la cartella `/content/` è vuota.\nDevi quindi **caricare il tuo PDF prima di eseguire la conversione**.\n\n**Come caricare il file:**\n\n1. Nel pannello di sinistra clicca sull'icona **File**.\n2. Trascina il PDF nella cartella `/content/` (radice della sessione), oppure clicca il pulsante *Carica* (icona freccia su).\n3. Attendi che il caricamento sia completato: il file comparirà nell'elenco.\n\nIn alternativa puoi caricare via codice:\n\n```python\nfrom google.colab import files\nuploaded = files.upload() # apre il selettore file\n```\n\nUna volta caricato, il PDF si trova in `/content/.pdf`.\nSostituisci `mio_documento.pdf` nella cella seguente con il nome del tuo file:" + "source": [ + "#### **Converti un singolo PDF**\n", + "\n", + "Su Google Colab il file system è temporaneo: ogni volta che avvii una nuova sessione la cartella `/content/` è vuota.\n", + "Devi quindi **caricare il tuo PDF prima di eseguire la conversione**.\n", + "\n", + "**Come caricare il file:**\n", + "\n", + "1. Nel pannello di sinistra clicca sull'icona **File**.\n", + "2. Trascina il PDF nella cartella `/content/` (radice della sessione), oppure clicca il pulsante *Carica* (icona freccia su).\n", + "3. Attendi che il caricamento sia completato: il file comparirà nell'elenco.\n", + "\n", + "In alternativa puoi caricare via codice:\n", + "\n", + "```python\n", + "from google.colab import files\n", + "uploaded = files.upload() # apre il selettore file\n", + "```\n", + "\n", + "Una volta caricato, il PDF si trova in `/content/.pdf`.\n", + "Sostituisci `mio_documento.pdf` nella cella seguente con il nome del tuo file:" + ] }, { "cell_type": "code", @@ -151,7 +177,9 @@ "outputId": "dc56bcc0-6e84-432a-8511-e461ff605a51" }, "outputs": [], - "source": "!mineru -p {PDF_NAME} -o ./output -b pipeline" + "source": [ + "!mineru -p {PDF_NAME} -o ./output -b pipeline" + ] }, { "cell_type": "code", @@ -166,41 +194,36 @@ }, "outputs": [], "source": [ - "import os, io\n", - "import fitz\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "from IPython.display import display\n", + "import os, zipfile, shutil\n", "\n", - "os.system('pip install -q pymupdf')\n", - "\n", - "# Cerca il layout PDF nell'output di MinerU (backend auto o hybrid_auto)\n", + "# Cerca la cartella di output (backend auto o hybrid_auto)\n", "candidates = [\n", - " f'./output/{STEM}/hybrid_auto/{STEM}_layout.pdf',\n", - " f'./output/{STEM}/auto/{STEM}_layout.pdf',\n", + " f'./output/{STEM}/hybrid_auto',\n", + " f'./output/{STEM}/auto',\n", + " f'./output/{STEM}',\n", "]\n", - "pdf_path = next((p for p in candidates if os.path.exists(p)), None)\n", + "output_dir = next((p for p in candidates if os.path.isdir(p)), None)\n", "\n", - "if pdf_path is None:\n", - " print('Layout PDF non trovato. Percorsi cercati:')\n", + "if output_dir is None:\n", + " print(f'Cartella output non trovata per \"{STEM}\". Percorsi cercati:')\n", " for p in candidates:\n", " print(' ', p)\n", "else:\n", - " doc = fitz.open(pdf_path)\n", - " n_pages = min(len(doc), 2) # mostra al massimo 2 pagine\n", - " fig, axes = plt.subplots(1, n_pages, figsize=(12 if n_pages > 1 else 6, 8))\n", - " if n_pages == 1:\n", - " axes = [axes]\n", - " for idx in range(n_pages):\n", - " pix = doc.load_page(idx).get_pixmap()\n", - " img = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, pix.n)\n", - " axes[idx].imshow(img)\n", - " axes[idx].axis('off')\n", - " axes[idx].set_title(f'Pagina {idx + 1}')\n", - " plt.tight_layout()\n", - " plt.show()\n", - " doc.close()\n", - " print(f'Layout da: {pdf_path}')\n" + " zip_path = f'./{STEM}_output.zip'\n", + " with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zf:\n", + " for root, dirs, files in os.walk(output_dir):\n", + " for file in files:\n", + " full_path = os.path.join(root, file)\n", + " arcname = os.path.relpath(full_path, start=os.path.dirname(output_dir))\n", + " zf.write(full_path, arcname)\n", + " size_mb = os.path.getsize(zip_path) / (1024 * 1024)\n", + " print(f'ZIP creato: {zip_path} ({size_mb:.1f} MB)')\n", + "\n", + " try:\n", + " from google.colab import files\n", + " files.download(zip_path)\n", + " except ImportError:\n", + " print('(download automatico disponibile solo su Google Colab)')\n" ] }, { @@ -208,7 +231,17 @@ "metadata": { "id": "t53WETM90pKr" }, - "source": "#### **Converti più PDF nella stessa cartella**\n\nConverte tutti i PDF presenti in `/content/` in un'unica esecuzione.\n\nCarica i file prima di eseguire la cella (trascina i PDF nel pannello File a sinistra oppure usa `files.upload()`).\n\nL'output di ogni PDF viene salvato in `./output//auto/`.\n\n> Usa questa cella al posto di quella precedente se hai più documenti da convertire." + "source": [ + "#### **Converti più PDF nella stessa cartella**\n", + "\n", + "Converte tutti i PDF presenti in `/content/` in un'unica esecuzione.\n", + "\n", + "Carica i file prima di eseguire la cella (trascina i PDF nel pannello File a sinistra oppure usa `files.upload()`).\n", + "\n", + "L'output di ogni PDF viene salvato in `./output//auto/`.\n", + "\n", + "> Usa questa cella al posto di quella precedente se hai più documenti da convertire." + ] }, { "cell_type": "code", @@ -220,100 +253,7 @@ "id": "4dqBGZiz0orA", "outputId": "8233269d-d912-4dd3-9332-d26bd464db7c" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[32m2026-04-23 11:36:57.400\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mmineru.cli.client\u001b[0m:\u001b[36mrun_orchestrated_cli\u001b[0m:\u001b[36m874\u001b[0m - \u001b[1mStarted local mineru-api at http://127.0.0.1:37453\u001b[0m\n", - "\u001b[32m2026-04-23 11:37:00.858\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36m__main__\u001b[0m:\u001b[36mcreate_app\u001b[0m:\u001b[36m260\u001b[0m - \u001b[1mRequest concurrency limited to 3\u001b[0m\n", - "Start MinerU FastAPI Service: http://127.0.0.1:37453\n", - "API documentation: http://127.0.0.1:37453/docs\n", - "\u001b[32mINFO\u001b[0m: Started server process [\u001b[36m10876\u001b[0m]\n", - "\u001b[32mINFO\u001b[0m: Waiting for application startup.\n", - "\u001b[32mINFO\u001b[0m: Application startup complete.\n", - "\u001b[32mINFO\u001b[0m: Uvicorn running on \u001b[1mhttp://127.0.0.1:37453\u001b[0m (Press CTRL+C to quit)\n", - "\u001b[32m2026-04-23 11:37:01.423\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mmineru.cli.client\u001b[0m:\u001b[36mrun_planned_task\u001b[0m:\u001b[36m771\u001b[0m - \u001b[1mSubmitting batch 1/1 | 2 documents, 19 pages in this batch | 19 pages total | task#1 [demo1, demo2]\u001b[0m\n", - "2026-04-23 11:37:06.518957: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:467] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n", - "WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\n", - "E0000 00:00:1776944226.544180 10908 cuda_dnn.cc:8579] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n", - "E0000 00:00:1776944226.552343 10908 cuda_blas.cc:1407] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n", - "W0000 00:00:1776944226.572768 10908 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n", - "W0000 00:00:1776944226.572813 10908 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n", - "W0000 00:00:1776944226.572818 10908 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n", - "W0000 00:00:1776944226.572821 10908 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n", - "2026-04-23 11:37:06.578247: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n", - "To enable the following instructions: AVX2 AVX512F FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", - "\u001b[32m2026-04-23 11:37:11.673\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mmineru.backend.pipeline.pipeline_analyze\u001b[0m:\u001b[36mdoc_analyze_streaming\u001b[0m:\u001b[36m183\u001b[0m - \u001b[1mPipeline processing-window multi-file run. doc_count=2, total_pages=19, window_size=64, total_batches=1\u001b[0m\n", - "\u001b[32m2026-04-23 11:37:17.154\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mmineru.backend.pipeline.pipeline_analyze\u001b[0m:\u001b[36mdoc_analyze_streaming\u001b[0m:\u001b[36m235\u001b[0m - \u001b[1mPipeline processing window batch 1/1: 19/19 pages, batch_pages=19, doc_slices=doc0:1-13,doc1:1-6\u001b[0m\n", - "\u001b[32m2026-04-23 11:37:17.158\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mmineru.backend.pipeline.pipeline_analyze\u001b[0m:\u001b[36mbatch_image_analyze\u001b[0m:\u001b[36m328\u001b[0m - \u001b[1mGPU Memory: 15 GB, Batch Ratio: 4. \u001b[0m\n", - "\u001b[32m2026-04-23 11:37:17.160\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mmineru.backend.pipeline.model_init\u001b[0m:\u001b[36m__init__\u001b[0m:\u001b[36m207\u001b[0m - \u001b[1mDocAnalysis init, this may take some times......\u001b[0m\n", - "Fetching 7 files: 100% 7/7 [00:00<00:00, 72494.14it/s]\n", - "Fetching 3 files: 100% 3/3 [00:00<00:00, 20004.63it/s]\n", - "Fetching 1 files: 100% 1/1 [00:00<00:00, 7244.05it/s]\n", - "Fetching 1 files: 100% 1/1 [00:00<00:00, 8160.12it/s]\n", - "Fetching 1 files: 100% 1/1 [00:00<00:00, 7653.84it/s]\n", - "Fetching 1 files: 100% 1/1 [00:00<00:00, 21183.35it/s]\n", - "Fetching 1 files: 0% 0/1 [00:00