Actualización del 2025-06-15 a las 22:45:55

This commit is contained in:
jlimolina 2025-06-15 22:45:55 +02:00
parent 603149d47a
commit eb72ec9e56
5 changed files with 114 additions and 94 deletions

73
app.py
View file

@ -93,7 +93,8 @@ def home():
paises = cursor.fetchall()
sql_params, conditions = [], []
sql_base = "SELECT n.fecha, n.titulo, n.resumen, n.url, n.imagen_url, c.nombre AS categoria, p.nombre AS pais, co.nombre AS continente FROM noticias n LEFT JOIN categorias c ON n.categoria_id = c.id LEFT JOIN paises p ON n.pais_id = p.id LEFT JOIN continentes co ON p.continente_id = co.id"
# --- CORRECCIÓN: SE AÑADE 'fuente_nombre' AL SELECT ---
sql_base = "SELECT n.fecha, n.titulo, n.resumen, n.url, n.imagen_url, n.fuente_nombre, c.nombre AS categoria, p.nombre AS pais, co.nombre AS continente FROM noticias n LEFT JOIN categorias c ON n.categoria_id = c.id LEFT JOIN paises p ON n.pais_id = p.id LEFT JOIN continentes co ON p.continente_id = co.id"
if q:
search_query = " & ".join(q.split())
@ -361,40 +362,44 @@ def scrape_url():
flash("Debes seleccionar una fuente para procesar.", "error")
return redirect(url_for('scrape_url'))
source = None
try:
with get_conn() as conn:
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cursor:
cursor.execute("SELECT * FROM fuentes_url WHERE id = %s", (source_id,))
source = cursor.fetchone()
if not source:
flash("La fuente seleccionada no existe.", "error")
return redirect(url_for('scrape_url'))
lista_noticias, message = process_newspaper_url(source['url'], source['categoria_id'], source['pais_id'], source['idioma'])
if lista_noticias:
# Se necesita una nueva conexión/cursor para la inserción
with get_conn() as insert_conn:
with insert_conn.cursor() as insert_cursor:
insert_query = """
INSERT INTO noticias (id, titulo, resumen, url, fecha, imagen_url, categoria_id, pais_id)
VALUES %s
ON CONFLICT (url) DO UPDATE SET
titulo = EXCLUDED.titulo,
resumen = EXCLUDED.resumen,
fecha = EXCLUDED.fecha,
imagen_url = EXCLUDED.imagen_url;
"""
psycopg2.extras.execute_values(insert_cursor, insert_query, lista_noticias)
flash(f"Se encontraron y guardaron {len(lista_noticias)} noticias desde '{source['nombre']}'.", "success")
return redirect(url_for("home"))
else:
flash(message, "warning")
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al procesar fuente URL: {db_err}", exc_info=True)
flash(f"Error de base de datos al procesar la fuente: {db_err}", "error")
app.logger.error(f"[DB ERROR] Al buscar fuente URL: {db_err}", exc_info=True)
flash("Error de base de datos al buscar la fuente.", "error")
return redirect(url_for('scrape_url'))
if not source:
flash("La fuente seleccionada no existe.", "error")
return redirect(url_for('scrape_url'))
lista_noticias, message = process_newspaper_url(source['nombre'], source['url'], source['categoria_id'], source['pais_id'], source['idioma'])
if lista_noticias:
try:
with get_conn() as conn:
with conn.cursor() as cursor:
insert_query = """
INSERT INTO noticias (id, titulo, resumen, url, fecha, imagen_url, fuente_nombre, categoria_id, pais_id)
VALUES %s
ON CONFLICT (url) DO UPDATE SET
titulo = EXCLUDED.titulo,
resumen = EXCLUDED.resumen,
fecha = EXCLUDED.fecha,
imagen_url = EXCLUDED.imagen_url;
"""
psycopg2.extras.execute_values(cursor, insert_query, lista_noticias)
flash(f"Se encontraron y guardaron {len(lista_noticias)} noticias desde '{source['nombre']}'.", "success")
return redirect(url_for("home"))
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al insertar noticias scrapeadas: {db_err}", exc_info=True)
flash(f"Error de base de datos al guardar las noticias: {db_err}", "error")
else:
flash(message, "warning")
return redirect(url_for('scrape_url'))
@ -437,7 +442,7 @@ def backup_noticias():
try:
with get_conn() as conn:
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cursor:
cursor.execute("SELECT n.id, n.titulo, n.resumen, n.url, n.fecha, n.imagen_url, c.nombre AS categoria, p.nombre AS pais, co.nombre AS continente FROM noticias n LEFT JOIN categorias c ON n.categoria_id = c.id LEFT JOIN paises p ON n.pais_id = p.id LEFT JOIN continentes co ON p.continente_id = co.id ORDER BY n.fecha DESC")
cursor.execute("SELECT n.id, n.titulo, n.resumen, n.url, n.fecha, n.imagen_url, n.fuente_nombre, c.nombre AS categoria, p.nombre AS pais, co.nombre AS continente FROM noticias n LEFT JOIN categorias c ON n.categoria_id = c.id LEFT JOIN paises p ON n.pais_id = p.id LEFT JOIN continentes co ON p.continente_id = co.id ORDER BY n.fecha DESC")
noticias = cursor.fetchall()
if not noticias:
flash("No hay noticias para exportar.", "warning")
@ -471,7 +476,7 @@ def backup_completo():
writer.writerows([dict(f) for f in feeds_data])
zipf.writestr("feeds.csv", output.getvalue())
cursor.execute("SELECT n.id, n.titulo, n.resumen, n.url, n.fecha, n.imagen_url, c.nombre AS categoria, p.nombre AS pais, co.nombre AS continente FROM noticias n LEFT JOIN categorias c ON n.categoria_id = c.id LEFT JOIN paises p ON n.pais_id = p.id LEFT JOIN continentes co ON p.continente_id = co.id ORDER BY n.fecha DESC")
cursor.execute("SELECT n.id, n.titulo, n.resumen, n.url, n.fecha, n.imagen_url, n.fuente_nombre, c.nombre AS categoria, p.nombre AS pais, co.nombre AS continente FROM noticias n LEFT JOIN categorias c ON n.categoria_id = c.id LEFT JOIN paises p ON n.pais_id = p.id LEFT JOIN continentes co ON p.continente_id = co.id ORDER BY n.fecha DESC")
noticias_data = cursor.fetchall()
if noticias_data:
fieldnames_noticias = list(noticias_data[0].keys())
@ -543,7 +548,8 @@ def fetch_and_store():
with get_conn() as conn:
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cursor:
logging.info("Paso 1: Obteniendo lista de feeds...")
cursor.execute("SELECT id, url, categoria_id, pais_id, last_etag, last_modified FROM feeds WHERE activo = TRUE")
# --- CORRECCIÓN: Se añade 'nombre' al SELECT ---
cursor.execute("SELECT id, nombre, url, categoria_id, pais_id, last_etag, last_modified FROM feeds WHERE activo = TRUE")
feeds_to_process = cursor.fetchall()
logging.info(f"Paso 2: {len(feeds_to_process)} feeds para procesar.")
except psycopg2.Error as db_err:
@ -608,9 +614,10 @@ def fetch_and_store():
if todas_las_noticias:
logging.info(f"Intentando insertar {len(todas_las_noticias)} noticias en la base de datos.")
with conn.cursor() as cursor_news_insert:
# --- CORRECCIÓN: Se añade 'fuente_nombre' a la consulta INSERT ---
psycopg2.extras.execute_values(
cursor_news_insert,
"INSERT INTO noticias (id, titulo, resumen, url, fecha, imagen_url, categoria_id, pais_id) VALUES %s ON CONFLICT (id) DO NOTHING",
"INSERT INTO noticias (id, titulo, resumen, url, fecha, imagen_url, fuente_nombre, categoria_id, pais_id) VALUES %s ON CONFLICT (url) DO NOTHING",
todas_las_noticias
)
rows_inserted = cursor_news_insert.rowcount