diff --git a/threads04/scraping.py b/threads04/scraping.py new file mode 100644 index 0000000..d45c222 --- /dev/null +++ b/threads04/scraping.py @@ -0,0 +1,139 @@ +import threading +import requests +from bs4 import BeautifulSoup +import mysql.connector +import queue + +# Colas para la comunicación entre los hilos +scraping_queue = queue.Queue() +link_queue = queue.Queue() + +# Conexión a la base de datos MySQL +db_conn = mysql.connector.connect( + host="localhost", # Cambia según tu configuración de MySQL + user="thread04", # Tu usuario de MySQL + password="1234", # Tu contraseña de MySQL + database="thread04" # Nombre de la base de datos +) + +# Hilo A: Realiza el scraping sobre una página web +def scraping_thread(): + while True: + url = scraping_queue.get() + if url is None: + break + print(f"[Hilo A] Scraping de {url}") + + try: + response = requests.get(url) + if response.status_code == 200: + soup = BeautifulSoup(response.content, 'html.parser') + page_text = soup.get_text() + links = [a['href'] for a in soup.find_all('a', href=True)] + + # Pasar el texto al hilo C y los enlaces al hilo B + scraping_data_queue.put((url, page_text)) + link_queue.put(links) + else: + print(f"[Hilo A] Error al acceder a {url}: {response.status_code}") + except Exception as e: + print(f"[Hilo A] Excepción durante scraping: {str(e)}") + finally: + scraping_queue.task_done() + +# Hilo B: Procesa los enlaces encontrados por el hilo A +def link_processing_thread(): + while True: + links = link_queue.get() + if links is None: + break + print(f"[Hilo B] Procesando {len(links)} enlaces") + + # Guardar los enlaces en la base de datos (hilo D) + for link in links: + link_database_queue.put(link) + + link_queue.task_done() + +# Hilo C: Guarda la información del scraping en un archivo +def save_to_file_thread(): + while True: + url, page_text = scraping_data_queue.get() + if url is None: + break + print(f"[Hilo C] Guardando datos de {url}") + with open("scraping_output.txt", "a", encoding='utf-8') as file: + file.write(f"\n\nURL: {url}\n\n{page_text}\n") + scraping_data_queue.task_done() + +# Hilo D: Guarda los enlaces en la base de datos MySQL y los vuelve a pasar al hilo A +def save_to_database_thread(): + while True: + link = link_database_queue.get() + if link is None: + break + print(f"[Hilo D] Guardando enlace en base de datos: {link}") + cursor = db_conn.cursor() + + try: + cursor.execute("INSERT INTO enlaces (url) VALUES (%s)", (link,)) + db_conn.commit() + + # Añadir el enlace a la cola de scraping para ser procesado por el hilo A + scraping_queue.put(link) + except mysql.connector.Error as err: + print(f"[Hilo D] Error de base de datos: {err}") + finally: + cursor.close() + link_database_queue.task_done() + +# Inicializar colas para comunicación +scraping_data_queue = queue.Queue() +link_database_queue = queue.Queue() + +# Crear tablas si no existen +def create_database(): + cursor = db_conn.cursor() + cursor.execute(""" + CREATE TABLE IF NOT EXISTS enlaces ( + id INT AUTO_INCREMENT PRIMARY KEY, + url VARCHAR(255) NOT NULL + ) + """) + db_conn.commit() + cursor.close() + +# Iniciar el programa +def main(): + create_database() + + # URLs iniciales para comenzar el scraping + initial_url = "http://localhost:8081/thread04/index.html" + + scraping_queue.put(initial_url) + + # Iniciar los hilos + thread_a = threading.Thread(target=scraping_thread, daemon=True) + thread_b = threading.Thread(target=link_processing_thread, daemon=True) + thread_c = threading.Thread(target=save_to_file_thread, daemon=True) + thread_d = threading.Thread(target=save_to_database_thread, daemon=True) + + thread_a.start() + thread_b.start() + thread_c.start() + thread_d.start() + + # Esperar a que terminen las colas + scraping_queue.join() + link_queue.join() + scraping_data_queue.join() + link_database_queue.join() + + # Detener los hilos una vez finalizadas las tareas + scraping_queue.put(None) + link_queue.put(None) + scraping_data_queue.put(None) + link_database_queue.put(None) + +if __name__ == "__main__": + main()