Como validar e limpar emails em Python para dados: passo a passo
Aprender a validar e limpar emails em Python para dados é útil para melhorar a qualidade de bases de dados, reduzir falhas no envio de notificações e garantir melhor correspondência entre registos. Este tutorial mostra como detetar formatos inválidos, normalizar domínios comuns e eliminar duplicados de forma prática.
Pré-requisitos
- Python 3.8+ instalado.
- Bibliotecas: pandas, email-validator (instalação via pip).
- Editor de texto ou Jupyter Notebook.
Passo 1: Instalar dependências
Instale as bibliotecas necessárias. A biblioteca email-validator faz a validação sintáctica e algumas correcções básicas; pandas facilita a manipulação de dados.
pip install pandas email-validator
Passo 2: Carregar dados de exemplo
Crie um DataFrame simples com emails que contenham erros comuns: espaços, maiúsculas, pontos duplicados, domínios com typos e entradas vazias.
import pandas as pd
df = pd.DataFrame({
'id': [1,2,3,4,5,6],
'email': [
'Joao.Silva@Exemplo.COM ',
'maria..souza@@gmail.com',
'ana@gnail.con',
' ',
'pedro@exemplo.com',
'PEDRO@Exemplo.com'
]
})
print(df)
Passo 3: Normalizar strings básicas
Remova espaços em branco à volta, converta para minúsculas e reduza pontos duplicados na parte local do email. Isto reduz diferenças triviais entre endereços.
def normalize_basic(email):
if not isinstance(email, str):
return ''
e = email.strip().lower()
# reduzir pontos duplicados na parte antes do @
if '@' in e:
local, domain = e.split('@', 1)
while '..' in local:
local = local.replace('..', '.')
e = f"{local}@{domain}"
return e
df['email_norm'] = df['email'].apply(normalize_basic)
print(df[['email','email_norm']])
Passo 4: Validar sintaxe com email-validator
Use email-validator para verificar se o formato é válido e receber recomendações. A função abaixo retorna um estado e a versão normalizada pelo validador quando possível.
from email_validator import validate_email, EmailNotValidError
def validate_email_safe(email):
if not email:
return {'valid': False, 'reason': 'empty', 'email': ''}
try:
v = validate_email(email, check_deliverability=False)
return {'valid': True, 'reason': '', 'email': v.email}
except EmailNotValidError as e:
return {'valid': False, 'reason': str(e), 'email': ''}
res = df['email_norm'].apply(validate_email_safe)
res_df = pd.json_normalize(res)
df = pd.concat([df, res_df.add_prefix('val_')], axis=1)
print(df[['email_norm','val_valid','val_reason','val_email']])
Passo 5: Corrigir domínios comuns com typos
Muitos erros vêm de domínios escritos incorretamente (ex.: gnail -> gmail). Crie um dicionário de correcções para aplicar após a validação sintáctica.
COMMON_DOMAINS = {
'gnail.com': 'gmail.com',
'gnail.con': 'gmail.com',
'exemplo.com': 'exemplo.com', # exemplo pretendido
}
def fix_common_domain(email):
if not email or '@' not in email:
return email
local, domain = email.split('@', 1)
domain_fix = COMMON_DOMAINS.get(domain, domain)
return f"{local}@{domain_fix}"
# aplicar apenas onde há um email validado em val_email ou tentar usar email_norm
df['email_fixed'] = df['val_email'].where(df['val_email'] != '', df['email_norm']).apply(fix_common_domain)
print(df[['email_norm','val_email','email_fixed']])
Passo 6: Revalidar e marcar inválidos
Revalide os emails corrigidos para separar os que continuam inválidos. Mantenha uma coluna com o estado final: valid/invalid/unknown.
final_res = df['email_fixed'].apply(validate_email_safe)
final_df = pd.json_normalize(final_res)
df = pd.concat([df, final_df.add_prefix('final_')], axis=1)
def status(row):
if row['final_valid']:
return 'valid'
if not row['email_fixed']:
return 'invalid'
return 'invalid'
df['status'] = df.apply(status, axis=1)
print(df[['email','email_fixed','final_valid','status']])
Passo 7: Remover duplicados e consolidar
Ao normalizar e corrigir, é comum surgir duplicados (ex.: pedro@exemplo.com e PEDRO@Exemplo.com). Use pandas para deduplicar mantendo o primeiro registo ou agregando IDs.
# criar chave para deduplicar
clean = df[df['status']=='valid'].copy()
clean['email_canonical'] = clean['email_fixed']
# manter o primeiro id por email
clean_dedup = clean.drop_duplicates(subset=['email_canonical'], keep='first')
print(clean_dedup[['id','email','email_canonical']])
Verificar o resultado
Confirme que os emails válidos estão normalizados, inválidos identificados e duplicados removidos. Verifique números: total original, válidos finais, inválidos e duplicados removidos.
total = len(df)
validos = df['status'].eq('valid').sum()
invalidos = df['status'].eq('invalid').sum()
deduped = len(clean_dedup)
print(f"Total: {total}, Válidos: {validos}, Inválidos: {invalidos}, Após deduplicação: {deduped}")
Conclusão
Agora tem um processo simples para normalizar, validar e limpar emails em Python para dados, incluindo correcções de domínios e deduplicação. Próximos passos: integrar este pipeline num ETL, usar check_deliverability=True com cuidado ou enriquecer com validação SMTP. Dica: mantenha um registo das correcções para auditar alterações nos emails.