Spaces:
Paused
Paused
File size: 6,149 Bytes
31b7256 |
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 |
import pandas as pd
import re
import PyPDF2
from dizionario_acronimi import acronimi
import unicodedata
class DocumentProcessor:
"""
Classe per elaborare il testo dei documenti:
- Rimuove righe inutili basandosi su ESCLUDI_RE.
- Unisce righe spezzate in paragrafi coerenti, mantenendo gli elenchi puntati al paragrafo precedente.
- Suddivide il testo in paragrafi ben formattati.
"""
# 🔹 Lista di espressioni regolari per rimuovere righe indesiderate
ESCLUDI_RE = [
r'Pagina\s+\d+\s+di\s+\d+', # "Pagina x di y"
r'^Foglio\s+\d+', # "Foglio 3"
r'^\s*$', # Righe vuote
r'^Codice\s+Documento:\s+\w+', # "Codice Documento: ABC123"
r'^Firma\s+Digitale', # "Firma Digitale"
]
@staticmethod
def normalizza_testo_avanzato(testo):
if pd.isna(testo):
return ""
testo = str(testo).strip()
testo = testo.replace("’", "'").replace("‘", "'") # Sostituire tipi diversi di apostrofi
testo = unicodedata.normalize("NFKD", testo) # Normalizza Unicode (es: accenti, simboli)
return " ".join(testo.split()) # Rimuove spazi multipli
@staticmethod
def spezza_in_frammenti(testo: str, numero_frammenti : int = 1) ->list :
if numero_frammenti <= 0:
raise ValueError("Il numero di frammenti deve essere un intero positivo.")
lunghezza_testo = len(testo)
if numero_frammenti > lunghezza_testo:
return [] # Restituisce una lista vuota se non è possibile dividere
lunghezza_frammento = lunghezza_testo // numero_frammenti # Divisione intera
resto = lunghezza_testo % numero_frammenti # Calcola il resto
frammenti = []
inizio = 0
for i in range(numero_frammenti):
fine = inizio + lunghezza_frammento + (1 if i < resto else 0) # Gestisce il resto
frammenti.append(testo[inizio:fine])
inizio = fine
return frammenti
def estrai_da_pdf(self, pdf_file_path) :
with open(pdf_file_path, "rb") as f:
reader = PyPDF2.PdfReader(f)
full_text = ""
for page in reader.pages:
page_text = page.extract_text() or ""
full_text += page_text
for acr, espansione in acronimi.items():
full_text = full_text.replace(acr,espansione)
return full_text
def chunk_text_by_paragraph(self,text: str):
"""
Suddivide il testo in paragrafi basandosi su newline.
Mantiene uniti gli elenchi puntati e numerati con il paragrafo precedente.
"""
paragraphs = text.split("\n")
docs = []
for i, para in enumerate(paragraphs):
para = para.strip()
if para:
docs.append({"id": str(i), "text": para})
return docs
def scomponi_in_frammenti(self, testo:str, numero_frammenti: int = 1):
raise NotImplementedError("Questo metodo deve essere implementato nelle sottoclassi.")
def unify_lines(self, text):
"""
Metodo da implementare nelle sottoclassi per suddividere il testo in paragrafi.
"""
return "\n".join(self.dividi_in_paragrafi(text))
def dividi_in_paragrafi(self,pdf_text: str) :
"""
Unisce righe spezzate in paragrafi coerenti, evitando di separare gli elenchi puntati dal paragrafo precedente.
Filtra le righe che corrispondono a qualsiasi espressione regolare contenuta in ESCLUDI_RE.
"""
lines = pdf_text.splitlines()
paragraphs = []
current_line = ""
end_punctuations = (".", "?", "!", ":", ";")
inside_list = False # 🟢 Indica se stiamo dentro un elenco puntato
for line in lines:
line = line.strip()
# 🛑 Rimuove le righe che corrispondono a una delle regex in ESCLUDI_RE
if any(re.search(pattern, line, re.IGNORECASE) for pattern in DocumentProcessor.ESCLUDI_RE):
continue # ❌ Salta la riga
# 🟢 Riconosce un elemento di un elenco puntato (es. "- testo", "• testo", "1. testo")
is_list_item = re.match(r"^(\d+\.\s+|[-•*]\s+).+", line)
# 🟢 Se la riga è vuota e abbiamo testo nel buffer, chiudiamo il paragrafo
if not line:
if current_line:
paragraphs.append(current_line.strip())
current_line = ""
inside_list = False # 🛑 Reset della modalità elenco
continue
# 🟢 Se è un elemento di elenco, lo aggiungiamo direttamente al paragrafo precedente
if is_list_item:
inside_list = True # 🟢 Indichiamo che siamo dentro un elenco
current_line += " " + line # 🔄 Aggiunge la riga all'elenco senza creare un nuovo paragrafo
elif inside_list:
# 🛑 Se eravamo dentro un elenco e ora la riga NON fa parte dell'elenco
current_line += " " + line # ✅ Manteniamo tutto unito
inside_list = False # 🔄 Reset della modalità elenco
elif line.endswith(end_punctuations):
current_line += " " + line
paragraphs.append(current_line.strip())
current_line = ""
else:
current_line += " " + line # ✅ Unisce righe normali
if current_line.strip():
paragraphs.append(current_line.strip())
#i = 0
#for par in paragraphs:
# print(f"Paragrafo {i} - {par}")
# i = i+1
return paragraphs
class ParagraphDocumentProcessor(DocumentProcessor):
def scomponi_in_frammenti(self, testo:str, numero_frammenti: int = 1):
return self.dividi_in_paragrafi(testo)
class WholeTextDocumentProcessor(DocumentProcessor) :
def scomponi_in_frammenti(self, testo:str, numero_frammenti: int = 1):
print("WholeTextDocumeptProcessor !!!")
return [testo]
|