mejora de programación de indices

This commit is contained in:
2025-03-20 08:02:07 +01:00
parent e4dd85afa8
commit c5386c2d13
4 changed files with 56 additions and 13 deletions

2
app/indices.csv Normal file
View File

@ -0,0 +1,2 @@
us-spx-500;S&P 500;15:00;22:00
spain-35;IBEX 35;09:00;18:00
1 us-spx-500 S&P 500 15:00 22:00
2 spain-35 IBEX 35 09:00 18:00

View File

@ -1,2 +0,0 @@
us-spx-500
spain-35

View File

@ -3,16 +3,56 @@ from contextlib import asynccontextmanager
from database import Base, engine from database import Base, engine
from routes import router from routes import router
from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.background import BackgroundScheduler
from webscrapper import search_from_keywords_file, search_from_indices_file from apscheduler.triggers.cron import CronTrigger
from webscrapper import search_from_keywords_file, search_indice
import csv
from datetime import datetime, time
# Crear las tablas en MySQL si no existen # Crear las tablas en MySQL si no existen
Base.metadata.create_all(bind=engine) Base.metadata.create_all(bind=engine)
# Configurar el scheduler # Configurar el scheduler (solo una instancia)
scheduler = BackgroundScheduler() scheduler = BackgroundScheduler()
scheduler.add_job(search_from_keywords_file, "cron", hour=11, minute=0) #Ejecutar a las 01:00
scheduler.add_job(search_from_keywords_file, "cron", hour=18, minute=0) #Ejecutar a las 01:00 # Agregar tareas fijas
scheduler.add_job(search_from_indices_file, "interval", minutes=60) scheduler.add_job(search_from_keywords_file, "cron", hour=11, minute=0) # Ejecutar a las 11:00 AM
scheduler.add_job(search_from_keywords_file, "cron", hour=18, minute=0) # Ejecutar a las 6:00 PM
def cargar_tareas_desde_csv(indices):
"""Lee el CSV y agrega tareas al scheduler"""
try:
with open(indices, mode='r', encoding='utf-8') as file:
reader = csv.reader(file, delimiter=';')
for row in reader:
if len(row) < 4: # Verifica que haya suficientes columnas
print(f"❌ Línea incorrecta en CSV: {row}")
continue
url, nombre, horaInicio, horaFin = row # Extrae los valores
try:
horaInicio = datetime.strptime(horaInicio.strip(), "%H:%M").time()
horaFin = datetime.strptime(horaFin.strip(), "%H:%M").time()
except ValueError:
print(f"❌ Formato de hora incorrecto en línea: {row}")
continue
obj = {"url": url.strip(), "nombre": nombre.strip(), "horaInicio": horaInicio, "horaFin": horaFin}
# Programar ejecución solo dentro del rango de horas permitido
for hora in range(horaInicio.hour, horaFin.hour + 1):
scheduler.add_job(
search_indice,
trigger=CronTrigger(hour=hora, minute=0),
args=[obj]
)
print("✅ Tareas programadas correctamente.")
except Exception as e:
print(f"❌ Error al leer el archivo CSV: {e}")
@asynccontextmanager @asynccontextmanager
@ -27,3 +67,7 @@ app = FastAPI(lifespan=lifespan)
# Incluir rutas # Incluir rutas
app.include_router(router) app.include_router(router)
# Cargar tareas desde el CSV al iniciar
cargar_tareas_desde_csv("indices.csv")

View File

@ -205,13 +205,13 @@ def search_from_indices_file():
logging.info(f"Error al leer el archivo 'indices.txt': {e}") logging.info(f"Error al leer el archivo 'indices.txt': {e}")
def search_indice(indice): def search_indice(indice):
base_url = f"https://www.investing.com/indices/{indice}" base_url = f"https://www.investing.com/indices/{indice.url}"
try: try:
response = requests.get(base_url, headers=HEADERS) response = requests.get(base_url, headers=HEADERS)
if response.status_code != 200: if response.status_code != 200:
logging.info(f"Error al acceder a la página para la consulta '{indice}': {response.status_code}") logging.info(f"Error al acceder a la página para la consulta '{indice.nombre}': {response.status_code}")
return return
soup = BeautifulSoup(response.content, 'html.parser') soup = BeautifulSoup(response.content, 'html.parser')
@ -222,11 +222,10 @@ def search_indice(indice):
price_change = soup.find("span", {"data-test": "instrument-price-change"}) price_change = soup.find("span", {"data-test": "instrument-price-change"})
price_change_percent = soup.find("span", {"data-test": "instrument-price-change-percent"}) price_change_percent = soup.find("span", {"data-test": "instrument-price-change-percent"})
porcentaje = price_change_percent.text.strip().replace("(", "").replace(")", "").replace("%", "") porcentaje = price_change_percent.text.strip().replace("(", "").replace(")", "").replace("%", "")
indice_real = chart_inner_title.text.strip() if chart_inner_title else indice
if price and price_change and price_change_percent: if price and price_change and price_change_percent:
data = { data = {
"indice": indice_real, "indice": indice.nombre,
"valorActual": price.text.replace(",", "").strip(), # Convertir a número "valorActual": price.text.replace(",", "").strip(), # Convertir a número
"cambio": price_change.text.replace(",", "").strip(), # Convertir a número "cambio": price_change.text.replace(",", "").strip(), # Convertir a número
"porcentaje": porcentaje # Eliminar paréntesis "porcentaje": porcentaje # Eliminar paréntesis
@ -236,11 +235,11 @@ def search_indice(indice):
response_telegram = requests.post(TELEGRAM_BOT_URL, json=data) response_telegram = requests.post(TELEGRAM_BOT_URL, json=data)
if response_telegram.status_code == 200: if response_telegram.status_code == 200:
logging.info(f"Mensaje enviado a Telegram correctamente para '{indice}'") logging.info(f"Mensaje enviado a Telegram correctamente para '{indice.nombre}'")
else: else:
logging.error(f"Error enviando mensaje a Telegram: {response_telegram.status_code} - {response_telegram.text}") logging.error(f"Error enviando mensaje a Telegram: {response_telegram.status_code} - {response_telegram.text}")
else: else:
logging.info(f"No se encontraron datos para el índice '{indice}'.") logging.info(f"No se encontraron datos para el índice '{indice.nombre}'.")
except requests.RequestException as e: except requests.RequestException as e:
logging.error(f"Error en la solicitud: {e}") logging.error(f"Error en la solicitud: {e}")