mejora de programación de indices
This commit is contained in:
2
app/indices.csv
Normal file
2
app/indices.csv
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
us-spx-500;S&P 500;15:00;22:00
|
||||||
|
spain-35;IBEX 35;09:00;18:00
|
|
@ -1,2 +0,0 @@
|
|||||||
us-spx-500
|
|
||||||
spain-35
|
|
54
app/main.py
54
app/main.py
@ -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")
|
||||||
|
|
||||||
|
|
||||||
|
@ -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}")
|
||||||
|
Reference in New Issue
Block a user