import streamlit as st import pandas as pd import random import zipfile from faker import Faker from unidecode import unidecode from pathlib import Path from datetime import datetime from PyDictionary import PyDictionary faker = Faker('es_MX') def generar_rfc(nombre, apellido, anio, mes, dia): return f"{apellido[:2].upper()}{nombre[:2].upper()}{str(anio)[-2:]}{mes:02}{dia:02}{random.randint(10, 99)}" def generar_telefono_por_estado(estado): ladas = {'Ciudad de Mexico': '55', 'Jalisco': '33', 'Nuevo Leon': '81', 'Veracruz': '229', 'Yucatan': '999', 'Puebla': '222', 'Chiapas': '961', 'Tamaulipas': '834', 'Queretaro': '442', 'Coahuila': '871'} return f"{ladas.get(estado, '55')}{random.randint(1000000, 9999999)}" def generar_nss(): return f"{random.randint(100, 999)}-{random.randint(10, 99)}-{random.randint(1000, 9999)}" def limpiar_correo(correo): return unidecode(correo.replace(" ", "").lower()) def generar_correo_aleatorio(): try: diccionario = PyDictionary() palabra = random.choice(list(diccionario.meaning("word").keys())) except Exception: palabra = faker.word() dominio = random.choice(["gmail.com", "hotmail.com"]) return limpiar_correo(f"{palabra}{random.randint(1, 999)}@{dominio}") def generar_datos(cantidad, columnas, progreso): try: estados = ['Ciudad de Mexico', 'Jalisco', 'Nuevo Leon', 'Veracruz', 'Yucatan', 'Puebla', 'Chiapas', 'Tamaulipas', 'Queretaro', 'Coahuila'] bancos, datos = ['BBVA', 'Banorte', 'Santander', 'Citibanamex', 'HSBC', 'AMEX', 'Inbursa', 'Bancoppel'], [] for i in range(cantidad): estado = random.choice(estados) nombre, apellido = faker.first_name(), faker.last_name() dia, mes, anio = faker.date_of_birth().day, faker.date_of_birth().month, faker.date_of_birth().year fila = {'Nombre': f"{nombre} {apellido}" if 'Nombre' in columnas else None, 'RFC': generar_rfc(nombre, apellido, anio, mes, dia) if 'RFC' in columnas else None, 'Telefono': generar_telefono_por_estado(estado) if 'Telefono' in columnas else None, 'Estado': estado if 'Estado' in columnas else None, 'Direccion': faker.address() if 'Direccion' in columnas else None, 'Correo Electronico': generar_correo_aleatorio() if 'Correo Electronico' in columnas else None, 'Tarjeta': ''.join([str(random.randint(0, 9)) for _ in range(16)]) if 'Tarjeta' in columnas else None, 'Banco': random.choice(bancos) if 'Banco' in columnas else None, 'Score de Credito': random.randint(300, 850) if 'Score de Credito' in columnas else None, 'NSS': generar_nss() if 'NSS' in columnas else None} datos.append({k: v for k, v in fila.items() if v is not None}) if i % max(1, cantidad // 100) == 0: # Actualiza progreso proporcionalmente progreso.progress(i / cantidad) progreso.progress(1.0) return pd.DataFrame(datos) except Exception as e: raise RuntimeError(f"Error al generar datos: {e}") def guardar_varios_archivos(dfs, formato): archivos = [] try: for i, df in enumerate(dfs): timestamp = datetime.now().strftime("_%H%M%S") archivo_nombre = f"leads_buro_{i+1}{timestamp}." + ("csv" if formato == "CSV" else "xlsx") if formato == "CSV": df.to_csv(archivo_nombre, index=False) else: df.to_excel(archivo_nombre, index=False, engine='openpyxl') archivos.append(archivo_nombre) return archivos except Exception as e: raise RuntimeError(f"Error al guardar archivos: {e}") def crear_zip(archivos): try: zip_nombre = "archivos_generados.zip" with zipfile.ZipFile(zip_nombre, 'w') as zipf: for archivo in archivos: zipf.write(archivo, Path(archivo).name) for archivo in archivos: # Limpia archivos temporales Path(archivo).unlink(missing_ok=True) return zip_nombre except Exception as e: raise RuntimeError(f"Error al crear archivo ZIP: {e}") def main(): st.set_page_config(layout="wide") st.sidebar.title("Configuración") opciones_columnas = ["Nombre", "Telefono", "RFC", "Estado", "Direccion", "Correo Electronico", "Tarjeta", "Banco", "Score de Credito", "NSS"] columnas = [col for col in opciones_columnas if st.sidebar.checkbox(col, value=False)] num_archivos = st.sidebar.slider("Número de archivos (1M registros c/u):", min_value=1, max_value=25, value=1) formato_descarga = st.sidebar.radio("Selecciona el formato de descarga:", ["CSV", "XLS"]) if st.sidebar.button("Generar Datos"): try: if not columnas: st.error("Debe seleccionar al menos una columna.") return progreso = st.progress(0) st.write(f"Generando {num_archivos} archivo(s) de 1 millón de registros...") dfs = [generar_datos(1_000_000, columnas, progreso) for _ in range(num_archivos)] st.subheader("Previsualización de datos (primeros 100 registros del primer archivo):") st.dataframe(dfs[0].head(100)) archivos_generados = guardar_varios_archivos(dfs, formato_descarga) if len(archivos_generados) > 1: zip_nombre = crear_zip(archivos_generados) with open(zip_nombre, "rb") as file: st.download_button("Descargar todos en ZIP", data=file, file_name=zip_nombre, mime="application/zip") else: with open(archivos_generados[0], "rb") as file: st.download_button(f"Descargar {formato_descarga}", data=file, file_name=archivos_generados[0], mime="text/csv" if formato_descarga == "CSV" else "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") st.success("Archivos generados y listos para descargar.") except Exception as e: st.error(f"Error durante la generación: {e}") if __name__ == "__main__": main()