Commit inicial

This commit is contained in:
2024-08-05 10:46:20 -06:00
parent eb5f92e19c
commit 8f6b1f129e
32 changed files with 2101 additions and 0 deletions

217
sgu.py Normal file
View File

@@ -0,0 +1,217 @@
import numpy as np
from bs4 import BeautifulSoup
import psycopg2
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import argparse
import getpass
try:
# Configuración de Selenium
options = Options()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--window-size=1920x1080")
PATH = "/usr/bin/chromedriver"
service = Service(PATH)
driver = webdriver.Chrome(service=service, options=options)
except Exception as e:
print(f"Error configurando el navegador: {e}")
exit()
try:
# Parseo de argumentos
parser = argparse.ArgumentParser()
parser.add_argument("clave", help="Clave ULSA argument")
args = parser.parse_args()
clave = args.clave
# Solicitar la contraseña de manera segura
contraseña = getpass.getpass("Contraseña: ")
if not clave or not contraseña:
raise ValueError("Clave y/o contraseña no válidos")
except Exception as e:
print(f"Error en los argumentos: {e}")
driver.quit()
exit()
try:
# Navegar a la URL
url = "sgu.ulsa.edu.mx/psulsa/alumnos/consultainformacionalumnos/consultainformacion.aspx"
formatted_url = f"https://{clave}:{contraseña}@{url}"
driver.get(formatted_url)
driver.get(f'https://{url}')
except Exception as e:
print(f"Error navegando a la URL: {e}")
driver.quit()
exit()
try:
# If dentro del código existe un (case insensitive) Unauthorized
if "Unauthorized" in driver.page_source:
raise Exception("Credenciales inválidas")
elemento = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "ctl00_contenedor_HistorialAlumno1_lblBtnSeccionHAcademico"))
)
elemento.click()
except Exception as e:
print(f"Error interactuando con la página: {e}")
driver.quit()
exit()
try:
# Procesamiento de HTML con BeautifulSoup
html_doc = driver.page_source
soup = BeautifulSoup(html_doc, 'lxml')
table = soup.find('table', attrs={'id': 'ctl00_contenedor_HistorialAlumno1_gvMaterias'})
if table is None:
raise Exception("Tabla no encontrada en la página")
materias_sgu = []
headers = [header.text for header in table.find_all('th')]
def is_cell_empty(cell_content):
return not cell_content.strip() or cell_content == u'\xa0'
for row in table.find_all('tr'):
cols = row.find_all('td')
if cols and not any(is_cell_empty(col.text) for col in cols):
materias_sgu.append({headers[i]: col.text for i, col in enumerate(cols)})
for materia in materias_sgu:
materia['SEMESTRE'] = materia.pop('\xa0')
servicio_social = soup.find('span', attrs={'id': 'ctl00_contenedor_HistorialAlumno1_Header1_lblSS'}).text
# puede ser Realizado, No Realizado
if servicio_social == "No Realizado":
Alumno_serviciosocial = False
elif servicio_social == "Realizado":
Alumno_serviciosocial = True
except Exception as e:
print(f"Error procesando HTML: {e}")
exit()
finally:
driver.quit()
# Conexión a la base de datos y operaciones
conexion = psycopg2.connect(
dbname="sgi",
user="postgres",
password="sys4lci",
host="200.13.89.27",
port="5432"
)
# Ejecutar la consulta para actualizar public."Alumno"."Alumno_serviciosocial"
try:
with conexion.cursor() as cursor:
cursor.execute(f'UPDATE public."Alumno" SET "Alumno_serviciosocial" = {Alumno_serviciosocial} WHERE "Usuario_claveULSA" = \'{clave[2:]}\'')
conexion.commit()
except Exception as e:
print(f"Error al actualizar el servicio social: {e}")
if conexion:
conexion.rollback()
try:
# Ejecutar la consulta para obtener los periodos
with conexion.cursor() as cursor:
cursor.execute('SELECT * FROM "Periodo"')
Periodos = cursor.fetchall()
except Exception as e:
print(f"Error obteniendo los periodos de la base de datos: {e}")
try:
# Ejecutar la consulta para obtener los tipos de calificación
with conexion.cursor() as cursor:
cursor.execute('SELECT * FROM "TipoCalificacion"')
TiposCalificacion = cursor.fetchall()
except Exception as e:
print(f"Error obteniendo los tipos de calificación de la base de datos: {e}")
try:
# Ejecutar la consulta para obtener las materias base
with conexion.cursor() as cursor:
cursor.execute('SELECT * FROM "Materia"')
materias_base = cursor.fetchall()
except Exception as e:
print(f"Error obteniendo las materias de la base de datos: {e}")
try:
# Procesar y preparar las calificaciones para inserción/actualización
calificaciones = []
with conexion.cursor() as cursor:
cursor.execute(f'''
SELECT "Carrera_id", "PlanEstudio_id"
FROM "Alumno_view"
WHERE "Usuario_claveULSA" = {clave[2:]}
''')
Alumno_base = cursor.fetchone()
for materia_sgu in materias_sgu:
materia_base = next((materia_base for materia_base in materias_base if (materia_sgu['Cve ULSA'] in materia_base[-1] or materia_sgu['Cve SEP'] in materia_base[-1]) and (Alumno_base[1] == materia_base[0])), None)
if not materia_base:
continue
Periodo_base = next((Periodo_base for Periodo_base in Periodos if Periodo_base[-2] == materia_sgu['PERIODO']), None)
if not Periodo_base:
continue
Calificacion_base = next((Calificacion_base for Calificacion_base in TiposCalificacion if Calificacion_base[-2] == materia_sgu['EXAMEN']), None)
if not Calificacion_base:
raise Exception(f"No se encontró el tipo de calificación {materia_sgu['EXAMEN']} en la base de datos")
# buscar en la base de datos el grupo WHERE Grupo_desc = materia_sgu['GRUPO'] and if is not in the base insert it (note: semestre when printed in the console is '\xa0': '5')
with conexion.cursor() as cursor:
cursor.execute(f'''
SELECT "Grupo_id"
FROM "Grupo_view"
WHERE REGEXP_REPLACE("Grupo_desc", '[^\d]', '', 'g') = '{materia_sgu["GRUPO"]}' AND (("Carrera_id" = {Alumno_base[0]}) OR "Carrera_esComun")
''')
Grupo = cursor.fetchone()
if Grupo:
cursor.execute(f'''
INSERT INTO public."Alumno_Materia"("Usuario_claveULSA", "Materia_id", "Periodo_id", "Grupo_id")
VALUES ({clave[2:]}, {materia_base[0]}, {Periodo_base[0]}, {Grupo[0]})
ON CONFLICT ("Usuario_claveULSA", "Materia_id", "Periodo_id") DO NOTHING
;
''')
conexion.commit()
if not materia_base or not Periodo_base or not Calificacion_base:
print(f"No se encontraron coincidencias para la materia {materia_sgu['Cve ULSA']} o el periodo {materia_sgu['PERIODO']} o el tipo de calificación {materia_sgu['EXAMEN']}")
continue # Saltar esta iteración si alguna coincidencia falla
calificaciones.append(f"({clave[2:]}, {materia_base[0]}, {Periodo_base[0]}, {Calificacion_base[0]}, {materia_sgu['CALIF']}, CURRENT_DATE, 'SGU')")
if not calificaciones or len(calificaciones) == 0:
raise Exception("No hay calificaciones para insertar o actualizar.")
# Inserción/actualización de calificaciones en la base de datos
with conexion.cursor() as cursor:
cursor.execute(f'''
insert into "Alumno_Materia_Calificacion"
("Usuario_claveULSA", "Materia_id", "Periodo_id", "TipoCalificacion_id", "Calificacion_calif", "Calificacion_fecha", "Calificacion_comentario")
values
{','.join(calificaciones)}
on conflict ("Usuario_claveULSA", "Materia_id", "Periodo_id", "TipoCalificacion_id")
DO UPDATE SET "Calificacion_calif" = EXCLUDED."Calificacion_calif", "Calificacion_comentario" = EXCLUDED."Calificacion_comentario";
''')
conexion.commit()
except Exception as e:
print(f"Error al insertar/actualizar las calificaciones: {e} Stack: {e.__traceback__}")
# print the whole stack
if conexion:
conexion.rollback() # Revertir cambios en caso de error
conexion.close()