| import os |
| import time |
| import platform |
| import psutil |
| import socket |
| import requests |
| import pandas as pd |
| from pytrends.request import TrendReq |
| from dotenv import load_dotenv |
|
|
| |
| |
| |
| NOMBRE_PRODUCTO = "Funda de silicona para iPhone 16" |
| PALABRA_CLAVE_BUSQUEDA = "silicone case iPhone 16" |
| COSTO_TU_PRODUCTO_MXN = 85.0 |
| PESO_PRODUCTO_GRAMOS = 120 |
| PRECIO_VENTA_OBJETIVO_USD = 19.99 |
| EBAY_CLIENT_ID = "TU_CLIENT_ID_AQUI" |
| |
|
|
| load_dotenv() |
| EBAY_CLIENT_ID = os.getenv("EBAY_CLIENT_ID", EBAY_CLIENT_ID) |
| TIPO_CAMBIO_USD_MXN = 17.20 |
|
|
| |
| |
| |
| |
| def verificar_dispositivo_local() -> dict: |
| """ |
| Detecta SOLO el equipo donde se ejecuta el código (anónimo): |
| - Sistema operativo + versión |
| - CPU, núcleos, RAM total |
| - Espacio en disco libre |
| - Versión de Python instalada |
| - Hostname local (solo nombre de tu equipo en tu red, nada público) |
| NO LEE: IP pública, ubicación, GPS, archivos, cuentas, nada personal. |
| """ |
| try: |
| |
| so = f"{platform.system()} {platform.release()} ({platform.version()})" |
| arquitectura = platform.machine() |
| |
| |
| cpu_nombre = platform.processor() or "CPU genérico" |
| cpu_nucleos = psutil.cpu_count(logical=True) |
| cpu_uso_actual = psutil.cpu_percent(interval=0.5) |
| |
| |
| ram_total_gb = round(psutil.virtual_memory().total / (1024**3), 1) |
| ram_libre_gb = round(psutil.virtual_memory().available / (1024**3), 1) |
| |
| |
| disco = psutil.disk_usage(os.path.abspath(os.sep)) |
| disco_total_gb = round(disco.total / (1024**3), 1) |
| disco_libre_gb = round(disco.free / (1024**3), 1) |
| |
| |
| python_version = platform.python_version() |
| |
| |
| nombre_equipo = socket.gethostname() |
| |
| |
| es_real = ( |
| ram_total_gb >= 1 and |
| disco_total_gb >= 10 and |
| cpu_nucleos >= 1 and |
| python_version >= "3.8" |
| ) |
| estado = "✅ DISPOSITIVO REAL Y VÁLIDO" if es_real else "⚠️ EQUIPO CON POCOS RECURSOS" |
| |
| |
| print("="*60) |
| print(f"🔍 VERIFICACIÓN DE TU DISPOSITIVO (ejecutándose AHORA):") |
| print("="*60) |
| print(f" Equipo: {nombre_equipo}") |
| print(f" Sistema: {so} | {arquitectura}") |
| print(f" CPU: {cpu_nombre} ({cpu_nucleos} núcleos) | Uso ahora: {cpu_uso_actual}%") |
| print(f" RAM: {ram_libre_gb} GB libres de {ram_total_gb} GB total") |
| print(f" Disco: {disco_libre_gb} GB libres de {disco_total_gb} GB total") |
| print(f" Python: v{python_version}") |
| print(f" Estado: {estado}") |
| print(" ℹ️ Sin ubicación | Sin datos personales | Todo local\n") |
| |
| return { |
| "so": so, "cpu": cpu_nombre, "ram_gb": ram_total_gb, |
| "disco_gb": disco_total_gb, "python": python_version, |
| "es_valido": es_real, "estado": estado |
| } |
| except Exception as e: |
| print(f"\n⚠️ No se pudo verificar el dispositivo: {str(e)[:60]}") |
| return {"es_valido": True, "estado": "Verificación omitida"} |
|
|
| |
| |
| |
| def verificar_demanda_usa(palabra_clave: str) -> dict: |
| try: |
| pytrends = TrendReq(hl='en-US', tz=360) |
| pytrends.build_payload([palabra_clave], cat=0, timeframe='today 12-m', geo='US', gprop='') |
| datos = pytrends.interest_over_time() |
| if datos.empty: |
| return {"promedio":0,"actual":0,"tendencia":"Sin datos","ok":False} |
| prom = round(datos[palabra_clave].mean(),1) |
| act = round(datos[palabra_clave].iloc[-1],1) |
| tend = "CRECIENTE" if act>prom else "ESTABLE" if act==prom else "BAJANDO" |
| print(f"📊 DEMANDA EE.UU. (Google Trends):\n Prom 12m: {prom}/100 | Último mes: {act}/100 | Tendencia: {tend}\n") |
| return {"promedio":prom,"actual":act,"tendencia":tend,"ok":True} |
| except Exception as e: |
| print(f"⚠️ Google Trends no disponible: {str(e)[:50]}\n") |
| return {"promedio":0,"actual":0,"tendencia":"Error","ok":False} |
|
|
| |
| |
| |
| def precios_competencia_ebay(producto: str, client_id: str) -> dict: |
| if not client_id or client_id == "TU_CLIENT_ID_AQUI": |
| ref = round(PRECIO_VENTA_OBJETIVO_USD*0.95,2) |
| print(f"🏷️ COMPETENCIA (sin eBay ID): precios referencia ${ref} USD promedio\n") |
| return {"prom":ref,"min":round(ref*0.7,2),"max":round(ref*1.3,2),"n":0,"ok":False} |
| try: |
| r = requests.get( |
| "https://api.ebay.com/buy/browse/v1/item_summary/search", |
| headers={"Authorization":f"Bearer {client_id}","X-EBAY-C-MARKETPLACE-ID":"EBAY_US"}, |
| params={"q":producto,"limit":50,"filter":"conditions:{NEW}"}, |
| timeout=10 |
| ) |
| r.raise_for_status() |
| precios = [float(i["price"]["value"]) for i in r.json().get("itemSummaries",[]) if 5<float(i["price"]["value"])<500] |
| if not precios: |
| return {"prom":0,"min":0,"max":0,"n":0,"ok":False} |
| prom,mn,mx = round(sum(precios)/len(precios),2),round(min(precios),2),round(max(precios),2) |
| print(f"🏷️ COMPETENCIA eBay EE.UU. ({len(precios)} productos nuevos):\n Prom: ${prom} | Mín: ${mn} | Máx: ${mx}\n") |
| return {"prom":prom,"min":mn,"max":mx,"n":len(precios),"ok":True} |
| except Exception as e: |
| print(f"⚠️ eBay API error: {str(e)[:50]}\n") |
| return {"prom":PRECIO_VENTA_OBJETIVO_USD*0.95,"min":0,"max":0,"n":0,"ok":False} |
|
|
| |
| |
| |
| def calcular_envio_mxn(peso_g: float) -> dict: |
| kg = peso_g/1000 |
| |
| sepomex = 235 if kg<=0.5 else 389 if kg<=1 else 612 if kg<=2 else 612+(kg-2)*220 |
| |
| dhl = 890 if kg<=0.5 else 1120 if kg<=1 else 1450 if kg<=2 else 1450+(kg-2)*310 |
| print(f"📦 ENVÍO XALAPA → EE.UU. ({peso_g}g):\n SEPOMEX: ${round(sepomex,2)} MXN (${round(sepomex/TIPO_CAMBIO_USD_MXN,2)} USD) | 7-15d\n DHL: ${round(dhl,2)} MXN (${round(dhl/TIPO_CAMBIO_USD_MXN,2)} USD) | 2-3d\n") |
| return {"sepomex":round(sepomex,2),"dhl":round(dhl,2)} |
|
|
| |
| |
| |
| def calcular_rentabilidad(costo_mxn: float, precio_usd: float, envios: dict, comp: dict) -> dict: |
| p_mxn = precio_usd * TIPO_CAMBIO_USD_MXN |
| comision = p_mxn*0.13 |
| arancel = p_mxn*0.04 |
| iva_usa = p_mxn*0.07 |
| pago = p_mxn*0.03 + 5 |
| |
| res = {} |
| for nombre, env_mxn in [("SEPOMEX",envios["sepomex"]),("DHL",envios["dhl"])]: |
| ct = costo_mxn + env_mxn + comision + arancel + iva_usa + pago |
| gan = p_mxn - ct |
| marg = round((gan/p_mxn)*100,1) |
| rec = "✅ Precio competitivo" if precio_usd<=comp["prom"] else "⚠️ Más caro que la competencia" |
| rec += " | ❌ NO RENTABLE" if marg<10 else " | ✅ RENTABLE" if marg>20 else " | ⚠️ Margen bajo" |
| res[nombre] = { |
| "ingreso":round(p_mxn,2),"costo_total":round(ct,2), |
| "ganancia_mxn":round(gan,2),"ganancia_usd":round(gan/TIPO_CAMBIO_USD_MXN,2), |
| "margen":marg,"recomendacion":rec |
| } |
| print(f"💰 {nombre} (${precio_usd} USD):\n Ingreso: ${res[nombre]['ingreso']} MXN | Costo total: ${res[nombre]['costo_total']} MXN\n GANANCIA NETA: ${res[nombre]['ganancia_mxn']} MXN (${res[nombre]['ganancia_usd']} USD) | Margen: {marg}%\n {rec}\n") |
| return res |
|
|
| |
| |
| |
| if __name__ == "__main__": |
| |
| disp = verificar_dispositivo_local() |
| time.sleep(1) |
| |
| |
| if not disp["es_valido"]: |
| print("⚠️ Tu equipo tiene pocos recursos — el proceso puede ir lento, pero seguirá.\n") |
| |
| |
| print("="*60) |
| print(f"VALIDACIÓN DE PRODUCTO PARA VENDER EN EE.UU.: {NOMBRE_PRODUCTO.upper()}") |
| print("="*60) |
| |
| demanda = verificar_demanda_usa(PALABRA_CLAVE_BUSQUEDA) |
| time.sleep(2) |
| comp = precios_competencia_ebay(NOMBRE_PRODUCTO, EBAY_CLIENT_ID) |
| time.sleep(1) |
| envios = calcular_envio_mxn(PESO_PRODUCTO_GRAMOS) |
| rent = calcular_rentabilidad(COSTO_TU_PRODUCTO_MXN, PRECIO_VENTA_OBJETIVO_USD, envios, comp) |
| |
| |
| print("="*60) |
| print("🎯 CONCLUSIÓN FINAL PARA VENDER:") |
| print("="*60) |
| vende = disp["es_valido"] and demanda["actual"]>=30 and rent["SEPOMEX"]["margen"]>=15 |
| if vende: |
| print("🎉 SÍ VALE LA PENA: Tu equipo es válido + hay demanda + margen aceptable") |
| print(f" Acción: Empieza con SEPOMEX para probar, escala a DHL cuando vendas mucho.") |
| else: |
| print("❌ NO LO VENDAS ASÍ — ajusta algo:") |
| if not disp["es_valido"]: print(" → Actualiza Python a ≥3.8 o libera RAM/disco") |
| if demanda["actual"]<30: print(" → Cambia producto/palabra clave (poca demanda en EE.UU.)") |
| if rent["SEPOMEX"]["margen"]<15: print(" → Baja tu costo, sube el precio o reduce peso de envío") |
|
|