In questo veloce post ti parlo di una di quelle straordinarie, veloci, magiche, automazioni che è possibile realizzare con poche righe di codice in Pyhton.
È qualcosa sullo stile dei task illustrati in “Automate the Boring Stuff with Python“.
L’esigenza è la seguente:
prendere un PDF di più pagine, spezzettarlo e rinominare i singoli file estratti in base al contenuto della singola pagina.
Questo post ha del codice bello e pronto per le nostre esigenze: “Extract PDF Pages and Rename Based on Text in Each Page (Python)”.
Analizziamolo e comprendiamolo per adattarlo alle nostre esigenze.
Il processo
Il codice
# import the neccessary modules
import os, PyPDF2, re
# function to extract the individual pages from each pdf found
def split_pdf_pages(root_directory, extract_to_folder):
# traverse down through the root directory to sub-directories
for root, dirs, files in os.walk(root_directory):
for filename in files:
basename, extension = os.path.splitext(filename)
# if a file is a pdf
if extension == ".pdf":
# create a reference to the full filename path
fullpath = root + "\\" + basename + extension
# open the pdf in read mode
opened_pdf = PyPDF2.PdfFileReader(open(fullpath,"rb"))
# for each page in the pdf
for i in range(opened_pdf.numPages):
# write the page to a new pdf
output = PyPDF2.PdfFileWriter()
output.addPage(opened_pdf.getPage(i))
with open(extract_to_folder + "\\" + basename + "-%s.pdf" % i, "wb") as output_pdf:
output.write(output_pdf)
# function for renaming the single page pdfs based on text in the pdf
def rename_pdfs(extraced_pdf_folder, rename_folder):
# traverse down through the root directory to sub-directories
for root, dirs, files in os.walk(extraced_pdf_folder):
for filename in files:
basename, extension = os.path.splitext(filename)
# if a file is a pdf
if extension == ".pdf":
# create a reference to the full filename path
fullpath = root + "\\" + basename + extension
# open the individual pdf
pdf_file_obj = open(fullpath, "rb")
pdf_reader = PyPDF2.PdfFileReader(pdf_file_obj)
# access the individual page
page_obj = pdf_reader.getPage(0)
# extract the the text
pdf_text = page_obj.extractText()
# use regex to find information
for index in re.finditer("THE-DOC-PREFIX-", pdf_text):
doc_ext = pdf_text[index.end():index.end() + 14]
doc_num = "THE-DOC-PREFIX-" + doc_ext
pdf_file_obj.close()
# rename the pdf based on the information in the pdf
os.rename(fullpath, rename_folder + "\\" + doc_num + ".pdf")
# parameter variables
root_dir = r"C:\Users\******\Documents\rename_pdf"
extract_to = r"C:\Users\******\Documents\extracted"
rename_to = r"C:\Users\******\Documents\renamed"
# use the two functions
split_pdf_pages(root_dir, extract_to)
rename_pdfs(extract_to,rename_to)
Per prima cosa utilizzeremo tre moduli:
import os, PyPDF2, re
- os, per ravanare nella cartella dei file;
- PyPDF2, per eseguire le operazioni di split e lettura su PDF;
- re, per processare le espressioni regolari di ricerca e acquisizione del contenuto.
Lo script ha due funzioni essenziali:
- def split_pdf_pages, che cerca i PDF all’interno della cartella sorgente e splitta le singole pagine nella cartella di split. Questa funzione è costruita in modo che nella cartella di origine si possano caricare più file.
- rename_pdfs, che all’interno della cartella di split preleva i singoli PDF e, in base al risultato della ricerca dell’espressione regolare, rinomina i file in una nuova cartella di destinazione finale.
Le cartelle di origine, split/estrazione e rinomina finale sono definibili nelle seguenti variabili:
# parameter variables
root_dir = r"C:\Users\******\Documents\rename_pdf"
extract_to = r"C:\Users\******\Documents\extracted"
rename_to = r"C:\Users\******\Documents\renamed"
La parte, secondo me, interessante da comprendere è quella relativa la ricerca tramite espressione regolare:
# use regex to find information
for index in re.finditer("THE-DOC-PREFIX-", pdf_text):
doc_ext = pdf_text[index.end():index.end() + 14]
doc_num = "THE-DOC-PREFIX-" + doc_ext
pdf_file_obj.close()
# rename the pdf based on the information in the pdf
os.rename(fullpath, rename_folder + "\\" + doc_num + ".pdf")
Essenzialmente la funzione, in questo punto, all’apertura del ciclo for, va alla ricerca della porzione di testo “THE-DOC-PREFIX-” su file, e preleva i 14 caratteri successivi che ne seguono.
Alcune considerazioni che penso possano tornare utili quando proverai ad applicare lo script al singolo caso reale:
- l’acquisizione della stringa con cui rinominare il file può essere eseguita anche andando all’indietro, partendo dalla parola chiave ricercata nel PDF. In tal caso:
doc_ext = pdf_text[index.start() – 14: index.start()]
- non è detto che i 14 caratteri (o altro numero) acquisiti dalla ricerca siano sempre puliti puliti.
Con un po’ di lavoro sulla variabile string doc_ext puoi risolvere problemini vari e/o formattare il nome finale in modo più leggibile.
Due esempi relativi l’ultimo punto:
Puoi eliminare i primi 3 caratteri della stringa.
E rimuovere tutti gli spazi.
E rimuovere tutti gli “a capo”:
doc_num = "PREFISSO-A-PIACERE" + doc_ext[3:].replace(" ", "").replace("\n", "")
Oppure… puoi rimuovere una porzione di testo che non ti interessa dalla stringa:
doc_num = re.sub(r'\d+', '', doc_ext).replace("elimina questo testo", "")
Considera che il codice sopra riportato è scritto per Windows.
Se utilizzi lo script su Linux ricorda di modificare, oltre il formato delle variabili di percorso, anche quelle che dichiarano i relativi path.
Esempio:
fullpath = root + "/" + basename + extension
Discussione in tema su Reddit (per risolvere senza l’utilizzo di Python).