Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import torch | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification | |
| from urllib.parse import urlparse | |
| import io | |
| # --- CONFIGURAÇÕES --- | |
| # Seu ID do modelo (Correto conforme você enviou) | |
| MODEL_ID = "asilvamaia/ident_br" | |
| st.set_page_config(page_title="Validador .BR", page_icon="🇧🇷") | |
| # --- FUNÇÃO DE LIMPEZA --- | |
| def limpar_entrada(texto: str) -> str: | |
| """ | |
| Remove sujeira, portas, protocolos e www. | |
| """ | |
| texto = str(texto).strip().lower() | |
| if not texto: return "" | |
| # Mantém e-mail intacto para o modelo rejeitar explicitamente | |
| if "@" in texto: return texto | |
| # Garante protocolo para o urlparse funcionar corretamente | |
| if "http" not in texto and "://" not in texto: | |
| texto_temp = "http://" + texto | |
| else: | |
| texto_temp = texto | |
| try: | |
| parsed = urlparse(texto_temp) | |
| dominio_limpo = parsed.netloc if parsed.netloc else texto | |
| # Remove a porta (:8080) | |
| if ":" in dominio_limpo: | |
| dominio_limpo = dominio_limpo.split(':')[0] | |
| # Remove o 'www.' do início | |
| if dominio_limpo.startswith("www."): | |
| dominio_limpo = dominio_limpo[4:] | |
| return dominio_limpo | |
| except: | |
| return texto | |
| # --- CARREGAMENTO DO MODELO --- | |
| def load_model(): | |
| try: | |
| tokenizer = AutoTokenizer.from_pretrained(MODEL_ID) | |
| model = AutoModelForSequenceClassification.from_pretrained(MODEL_ID) | |
| # Força uso de CPU no Space gratuito para evitar erros | |
| model.to("cpu") | |
| model.eval() | |
| return tokenizer, model | |
| except Exception as e: | |
| st.error(f"Erro ao carregar modelo: {e}") | |
| return None, None | |
| tokenizer, model = load_model() | |
| # --- INTERFACE DO USUÁRIO --- | |
| st.title("🇧🇷 Validador de Domínios .BR") | |
| st.write("Faça upload de uma lista suja (.txt) para extrair apenas domínios .br válidos.") | |
| uploaded_file = st.file_uploader("Carregar arquivo .txt", type="txt") | |
| if uploaded_file and tokenizer: | |
| # Lê o arquivo enviado | |
| stringio = io.StringIO(uploaded_file.getvalue().decode("utf-8")) | |
| linhas = stringio.readlines() | |
| if st.button(f"Processar {len(linhas)} linhas"): | |
| validos = [] | |
| rejeitados = [] | |
| # Barra de progresso | |
| progress_bar = st.progress(0) | |
| total_linhas = len(linhas) | |
| for i, linha in enumerate(linhas): | |
| original = linha.strip() | |
| # --- CORREÇÃO DA LINHA QUE ESTAVA COM ERRO --- | |
| # Verifica se a linha é vazia ou se começa com metadados [source: ...] | |
| if not original or original.startswith("[source:"): | |
| continue | |
| # Aplica limpeza | |
| limpo = limpar_entrada(original) | |
| # Inferência (Classificação) | |
| inputs = tokenizer(limpo, return_tensors="pt", truncation=True, max_length=128) | |
| with torch.no_grad(): | |
| outputs = model(**inputs) | |
| pred = torch.argmax(outputs.logits, dim=1).item() | |
| # REGRA DE APROVAÇÃO: | |
| # 1. Modelo diz que é Classe 1 (BR) | |
| # 2. Tem ponto na string | |
| # 3. Não tem @ | |
| if pred == 1 and "." in limpo and "@" not in limpo: | |
| validos.append(limpo) | |
| else: | |
| rejeitados.append(original) | |
| # Atualiza barra de progresso a cada 10 itens | |
| if i % 10 == 0: | |
| progress_bar.progress(min((i + 1) / total_linhas, 1.0)) | |
| progress_bar.progress(1.0) | |
| # --- DEDUPLICAÇÃO (Remove repetidos) --- | |
| validos_unicos = sorted(list(set(validos))) | |
| rejeitados_unicos = sorted(list(set(rejeitados))) | |
| st.success("Processamento Concluído!") | |
| # Exibe métricas | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.metric("✅ Aprovados (Únicos)", len(validos_unicos), help="Domínios .br válidos") | |
| with col2: | |
| st.metric("🔴 Rejeitados (Únicos)", len(rejeitados_unicos), help="Itens descartados") | |
| # Botão de Download | |
| st.download_button( | |
| label="⬇️ Baixar Lista Limpa (.txt)", | |
| data="\n".join(validos_unicos), | |
| file_name="dominios_limpos.txt", | |
| mime="text/plain" | |
| ) | |
| # Mostra amostra | |
| with st.expander("Ver amostra dos resultados"): | |
| st.write(validos_unicos[:50]) |