Aggiungi script per verificare duplicati di email e numeri di telefono in un file Excel
This commit is contained in:
parent
ea9c84a395
commit
d663884521
3 changed files with 169 additions and 9 deletions
9
.claude/settings.local.json
Normal file
9
.claude/settings.local.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(python -c ' *)",
|
||||||
|
"Bash(python verifica_duplicati.py)",
|
||||||
|
"Bash(python verifica_duplicati.py \"data/No_Estensioni_Elenco_Volontari_al_2026-04-16_14_31_05.947610.xlsx\")"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -180,17 +180,17 @@ DESCRIZIONE:
|
||||||
5. Salva un nuovo file con suffisso "_modificato"
|
5. Salva un nuovo file con suffisso "_modificato"
|
||||||
|
|
||||||
UTILIZZO:
|
UTILIZZO:
|
||||||
python fixgaiaexcel.py <file_excel> [opzioni]
|
python fix_gaia_excel.py <file_excel> [opzioni]
|
||||||
|
|
||||||
ESEMPI:
|
ESEMPI:
|
||||||
# Estrae la data più vecchia (comportamento predefinito)
|
# Estrae la data più vecchia (comportamento predefinito)
|
||||||
python fixgaiaexcel.py "data/report.xlsx"
|
python fix_gaia_excel.py "data/report.xlsx"
|
||||||
|
|
||||||
# Estrae la data più recente
|
# Estrae la data più recente
|
||||||
python fixgaiaexcel.py "data/report.xlsx" --data-recente
|
python fix_gaia_excel.py "data/report.xlsx" --data-recente
|
||||||
|
|
||||||
# Mostra questo aiuto
|
# Mostra questo aiuto
|
||||||
python fixgaiaexcel.py --help
|
python fix_gaia_excel.py --help
|
||||||
|
|
||||||
OPZIONI:
|
OPZIONI:
|
||||||
--data-recente, --recente
|
--data-recente, --recente
|
||||||
|
|
@ -227,11 +227,11 @@ def main():
|
||||||
# Controlla gli argomenti da riga di comando
|
# Controlla gli argomenti da riga di comando
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print("Errore: File Excel non specificato\n")
|
print("Errore: File Excel non specificato\n")
|
||||||
print("Uso: python fixgaiaexcel.py <percorso_file_excel> [opzioni]")
|
print("Uso: python fix_gaia_excel.py <percorso_file_excel> [opzioni]")
|
||||||
print("\nEsempi:")
|
print("\nEsempi:")
|
||||||
print(" python fixgaiaexcel.py data/report.xlsx")
|
print(" python fix_gaia_excel.py data/report.xlsx")
|
||||||
print(" python fixgaiaexcel.py data/report.xlsx --data-recente")
|
print(" python fix_gaia_excel.py data/report.xlsx --data-recente")
|
||||||
print("\nPer maggiori informazioni: python fixgaiaexcel.py --help")
|
print("\nPer maggiori informazioni: python fix_gaia_excel.py --help")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Verifica se è stata richiesta la data più recente
|
# Verifica se è stata richiesta la data più recente
|
||||||
|
|
@ -242,7 +242,7 @@ def main():
|
||||||
|
|
||||||
if not file_args:
|
if not file_args:
|
||||||
print("Errore: Nessun file specificato")
|
print("Errore: Nessun file specificato")
|
||||||
print("\nPer maggiori informazioni: python fixgaiaexcel.py --help")
|
print("\nPer maggiori informazioni: python fix_gaia_excel.py --help")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
file_path = Path(file_args[0])
|
file_path = Path(file_args[0])
|
||||||
151
verifica_duplicati.py
Normal file
151
verifica_duplicati.py
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Verifica duplicati di Email e Numeri di Telefono in un file Excel dei soci.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import argparse
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
|
||||||
|
SEPARATORI_TELEFONO = re.compile(r"[;,/|\n]+")
|
||||||
|
|
||||||
|
|
||||||
|
def normalizza_email(email: str) -> str:
|
||||||
|
return str(email).strip().lower()
|
||||||
|
|
||||||
|
|
||||||
|
def normalizza_telefono(n: str) -> str:
|
||||||
|
"""Rimuove spazi interni dal numero (es. '344 503 2906' -> '3445032906')."""
|
||||||
|
return re.sub(r"\s+", "", n.strip())
|
||||||
|
|
||||||
|
|
||||||
|
def estrai_telefoni(cella: str) -> list[str]:
|
||||||
|
if not cella or str(cella).strip() in ("", "nan"):
|
||||||
|
return []
|
||||||
|
parti = SEPARATORI_TELEFONO.split(str(cella).strip())
|
||||||
|
return [normalizza_telefono(p) for p in parti if p.strip()]
|
||||||
|
|
||||||
|
|
||||||
|
def analizza_duplicati(filepath: str, esempi: int = 5):
|
||||||
|
print(f"\nCaricamento file: {filepath}")
|
||||||
|
df = pd.read_excel(filepath, dtype=str)
|
||||||
|
totale_righe = len(df)
|
||||||
|
print(f"Righe totali: {totale_righe}")
|
||||||
|
|
||||||
|
col_email = "Email"
|
||||||
|
col_tel = "Numeri di telefono"
|
||||||
|
|
||||||
|
if col_email not in df.columns:
|
||||||
|
print(f"[ERRORE] Colonna '{col_email}' non trovata. Colonne disponibili: {df.columns.tolist()}")
|
||||||
|
sys.exit(1)
|
||||||
|
if col_tel not in df.columns:
|
||||||
|
print(f"[ERRORE] Colonna '{col_tel}' non trovata. Colonne disponibili: {df.columns.tolist()}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# --- EMAIL ---
|
||||||
|
email_occorrenze: dict[str, list[int]] = defaultdict(list)
|
||||||
|
email_vuote = 0
|
||||||
|
|
||||||
|
for idx, val in df[col_email].items():
|
||||||
|
if pd.isna(val) or str(val).strip() == "":
|
||||||
|
email_vuote += 1
|
||||||
|
continue
|
||||||
|
norm = normalizza_email(val)
|
||||||
|
email_occorrenze[norm].append(idx + 2) # +2: header riga 1, indice 0-based
|
||||||
|
|
||||||
|
email_duplicate = {e: righe for e, righe in email_occorrenze.items() if len(righe) > 1}
|
||||||
|
email_uniche = len(email_occorrenze)
|
||||||
|
totale_email_duplicate = sum(len(r) - 1 for r in email_duplicate.values())
|
||||||
|
|
||||||
|
# --- TELEFONI ---
|
||||||
|
tel_occorrenze: dict[str, list[int]] = defaultdict(list)
|
||||||
|
tel_vuote = 0
|
||||||
|
totale_numeri_estratti = 0
|
||||||
|
|
||||||
|
for idx, val in df[col_tel].items():
|
||||||
|
if pd.isna(val) or str(val).strip() == "":
|
||||||
|
tel_vuote += 1
|
||||||
|
continue
|
||||||
|
numeri = estrai_telefoni(val)
|
||||||
|
totale_numeri_estratti += len(numeri)
|
||||||
|
for n in numeri:
|
||||||
|
tel_occorrenze[n].append(idx + 2)
|
||||||
|
|
||||||
|
tel_duplicate = {t: righe for t, righe in tel_occorrenze.items() if len(righe) > 1}
|
||||||
|
tel_uniche = len(tel_occorrenze)
|
||||||
|
totale_tel_duplicate = sum(len(r) - 1 for r in tel_duplicate.values())
|
||||||
|
|
||||||
|
# --- STAMPA REPORT ---
|
||||||
|
sep = "=" * 60
|
||||||
|
|
||||||
|
print(f"\n{sep}")
|
||||||
|
print(" REPORT DUPLICATI - EMAIL")
|
||||||
|
print(sep)
|
||||||
|
print(f" Righe totali : {totale_righe}")
|
||||||
|
print(f" Righe senza email : {email_vuote}")
|
||||||
|
print(f" Email univoche : {email_uniche}")
|
||||||
|
print(f" Email con duplicati : {len(email_duplicate)}")
|
||||||
|
print(f" Occorrenze duplicate extra : {totale_email_duplicate}")
|
||||||
|
|
||||||
|
top_email = sorted(email_duplicate.items(), key=lambda x: len(x[1]), reverse=True) if email_duplicate else []
|
||||||
|
|
||||||
|
if top_email:
|
||||||
|
n = min(esempi, len(top_email))
|
||||||
|
print(f"\n Top {n} email piu' duplicate:")
|
||||||
|
print(f" {'#':<4} {'Email':<40} {'Volte':>6} Righe Excel (prime 6)")
|
||||||
|
print(" " + "-" * 72)
|
||||||
|
for i, (email, righe) in enumerate(top_email[:n], 1):
|
||||||
|
righe_str = str(righe[:6])[1:-1] + ("..." if len(righe) > 6 else "")
|
||||||
|
print(f" {i:<4} {email:<40} {len(righe):>6} {righe_str}")
|
||||||
|
else:
|
||||||
|
print("\n Nessun duplicato trovato.")
|
||||||
|
|
||||||
|
print(f"\n{sep}")
|
||||||
|
print(" REPORT DUPLICATI - NUMERI DI TELEFONO")
|
||||||
|
print(sep)
|
||||||
|
print(f" Righe totali : {totale_righe}")
|
||||||
|
print(f" Righe senza telefono : {tel_vuote}")
|
||||||
|
print(f" Numeri totali estratti : {totale_numeri_estratti}")
|
||||||
|
print(f" Numeri univoci : {tel_uniche}")
|
||||||
|
print(f" Numeri con duplicati : {len(tel_duplicate)}")
|
||||||
|
print(f" Occorrenze duplicate extra : {totale_tel_duplicate}")
|
||||||
|
|
||||||
|
top_tel = sorted(tel_duplicate.items(), key=lambda x: len(x[1]), reverse=True) if tel_duplicate else []
|
||||||
|
|
||||||
|
if top_tel:
|
||||||
|
n = min(esempi, len(top_tel))
|
||||||
|
print(f"\n Top {n} numeri piu' duplicati:")
|
||||||
|
print(f" {'#':<4} {'Numero':<20} {'Volte':>6} Righe Excel (prime 6)")
|
||||||
|
print(" " + "-" * 60)
|
||||||
|
for i, (tel, righe) in enumerate(top_tel[:n], 1):
|
||||||
|
righe_str = str(righe[:6])[1:-1] + ("..." if len(righe) > 6 else "")
|
||||||
|
print(f" {i:<4} {tel:<20} {len(righe):>6} {righe_str}")
|
||||||
|
else:
|
||||||
|
print("\n Nessun duplicato trovato.")
|
||||||
|
|
||||||
|
print(f"\n{sep}")
|
||||||
|
print(" RIEPILOGO GENERALE")
|
||||||
|
print(sep)
|
||||||
|
pct_email = len(email_duplicate) / email_uniche * 100 if email_uniche else 0
|
||||||
|
pct_tel = len(tel_duplicate) / tel_uniche * 100 if tel_uniche else 0
|
||||||
|
print(f" Email duplicate : {len(email_duplicate):>5} ({pct_email:.1f}% delle email univoche)")
|
||||||
|
print(f" Telefoni duplicati : {len(tel_duplicate):>5} ({pct_tel:.1f}% dei numeri univoci)")
|
||||||
|
print(sep)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Verifica duplicati email e telefoni in un file Excel.")
|
||||||
|
parser.add_argument("file",
|
||||||
|
help="Percorso del file Excel da analizzare")
|
||||||
|
parser.add_argument("--esempi", type=int, default=5,
|
||||||
|
help="Numero di esempi da mostrare per categoria (default: 5)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
analizza_duplicati(args.file, args.esempi)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue