Commit inicial
This commit is contained in:
217
sgu.py
Normal file
217
sgu.py
Normal 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()
|
||||
Reference in New Issue
Block a user