opendatasicilia / tansignari

"T'ansignari e t'appeddiri"
http://tansignari.opendatasicilia.it
Creative Commons Attribution 4.0 International
18 stars 10 forks source link

Splittare un PDF usando un testo trappola #259

Closed pigreco closed 5 months ago

pigreco commented 5 months ago

File PDF con molte pagine, come splittarlo secondo un testo presente nel PDF.

Il testo è : ANDREA:testo_variabile

dove:

tutte le pagine del PDF che hanno stesso testo_variabile devono confluire in un unico PDF e quindi mi aspetto enne PDF multipagina.

aborruso commented 5 months ago

Caro @pigreco potresti prima estrarti un elenco di pagine con quella stringa, e poi usare quell'elenco per estrarti le varie parti.

A riga di comando io uso pdfgrep. Un comando "tipo" è

pdfgrep -n -o "ANDREA:[^ ]*" input.pdf >out.txt

In output avrai qualcosa come questa di sotto, in cui il numero iniziale è il numero di pagina:

1:ANDREA:Reggio_di_Calabria
2:ANDREA:Reggio_di_Calabria
3:ANDREA:Catania
4:ANDREA:Catania
5:ANDREA:Catania

Poi potresti crearti un jsonline, che è comodo per i loop per riga. Perché il jsonline è un formato in cui ogni linea è un oggetto json. Io uso miller

mlr --icsv --ojsonl --implicit-csv-header --ifs ":" label p,trappola,file then nest --ivar " " -f p out.txt >out.jsonl

Che in output ti dà

{"p": "1 2", "trappola": "ANDREA", "file": "Reggio_di_Calabria"}
{"p": "3 4 5", "trappola": "ANDREA", "file": "Catania"}

A quel punto hai i dati per "stampare" i due PDF a partire dalle relative pagine del pdf di input. Un tool è pdftk e il comando per stampare le pagine 1 e 2 in nuovo file è

pdftk input.pdf cat 1 2 output Reggio_di_Calabria.pdf

Non ti resta che inserire tutto in un loop di bash. Qui ti ho scritto diciamo la logica di base.

pigreco commented 5 months ago
  1. controlla se il file out.txt esiste, altrimenti lo crea
if [ ! -f out.txt ]; then
  pdfgrep -n -o "ANDREA:[^ ]*" input.pdf >out.txt
fi
  1. crea jsonline:
mlr --icsv --ojsonl --implicit-csv-header --ifs ":" label p,trappola,file then nest --ivar " " -f p out.txt >out.jsonl
  1. cicla
while read -r line; do
  pagine=$(echo "$line" | jq -r .p)
  file=$(echo "$line" | jq -r .file)

  eval pdftk input.pdf cat $pagine output "$file".pdf
done <out.jsonl
pigreco commented 5 months ago
#!/bin/bash

set -x
set -e
set -u
set -o pipefail

# if out exists, remove it
if [ ! -f out.txt ]; then
  pdfgrep -n -o "ANDREA:[^ ]*" input.pdf >out.txt
fi

mlr --icsv --ojsonl --implicit-csv-header --ifs ":" label p,trappola,file then nest --ivar " " -f p out.txt >out.jsonl

while read -r line; do
  pagine=$(echo "$line" | jq -r .p)
  file=$(echo "$line" | jq -r .file)

  eval pdftk input.pdf cat $pagine output "$file".pdf
done <out.jsonl
aborruso commented 5 months ago

wow, rapidissimo!

pigreco commented 5 months ago

Funziona benissimo, ho un PDF pesante sia in termini di pagine (≈ 800 ppgg) che di qualità lo script sembra lento impiega oltre 40 minuti

aborruso commented 5 months ago

Sulla velocità non ho un consiglio in particolare. Però di base basta che trovi un altro tool che estrae più rapidamente e lo usi al posto di pdftk. Ma la logica dello script è quella: dato un pdf, estrai elenco pagine/file_output ed estrai

pigreco commented 5 months ago

ricetta fatta e pubblicata

https://tansignari.opendatasicilia.it/ricette/bash/splittare_pdf_testo_trappola/

aborruso commented 5 months ago

Applausi