Menu iconMenu icon
Procesamiento de Lenguaje Natural con Python Edición Actualizada

Capítulo 12: Proyecto: Agregador de Noticias

12.4 Construcción de la Interfaz de Usuario

En esta sección, nos centraremos en la construcción de la interfaz de usuario (UI) para el chatbot agregador de noticias. La UI es crucial ya que permite a los usuarios interactuar con el chatbot y acceder a los artículos de noticias. Crearemos una interfaz web utilizando Flask, un marco web ligero para Python. Esta interfaz permitirá a los usuarios solicitar actualizaciones de noticias, ver resúmenes y explorar artículos de noticias categorizados.

12.4.1 Configuración de Flask

Primero, necesitamos instalar Flask si aún no lo hemos hecho:

pip install Flask

A continuación, configuremos la estructura básica de nuestra aplicación Flask.

app.py:

from flask import Flask, request, jsonify, render_template
from nlp_engine import preprocess_text, categorize_article
from summarizer import summarize_text, abstractive_summarize_text
from news_fetcher import fetch_news

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

@app.route('/get_news', methods=['POST'])
def get_news():
    category = request.form.get('category')
    articles = fetch_news(category)
    return jsonify(articles)

@app.route('/summarize', methods=['POST'])
def summarize():
    article = request.form.get('article')
    summary_type = request.form.get('summary_type')

    if summary_type == 'extractive':
        summary = summarize_text(article)
    else:
        summary = abstractive_summarize_text(article)

    return jsonify({'summary': summary})

if __name__ == '__main__':
    app.run(debug=True)

En este script, definimos las rutas básicas para nuestra aplicación Flask:

  • La ruta home renderiza la página de inicio.
  • La ruta get_news obtiene artículos de noticias basados en la categoría seleccionada.
  • La ruta summarize resume un artículo dado utilizando ya sea el resumen extractivo o el abstractivo.

12.4.2 Creación de Plantillas HTML

A continuación, crearemos plantillas HTML para renderizar las páginas web. Usaremos Bootstrap para el diseño y así crear una interfaz visualmente atractiva y receptiva.

templates/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <a href="${article.url}" target="_blank" class="list-group-item list-group-item-action">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                            </a>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });
    </script>
</body>
</html>

En esta plantilla HTML, creamos un formulario simple para seleccionar la categoría de noticias y un div para mostrar los artículos de noticias obtenidos. Usamos jQuery para manejar el envío del formulario y actualizar dinámicamente la página con los artículos de noticias obtenidos.

12.4.3 Integración de Resumen y Categorización

Para permitir a los usuarios ver resúmenes y categorizar artículos, necesitamos agregar funcionalidad adicional tanto en el frontend como en el backend.

app.py (continuación):

@app.route('/categorize', methods=['POST'])
def categorize():
    article = request.form.get('article')
    category = categorize_article(article)
    return jsonify({'category': category})

@app.route('/summarize_article', methods=['POST'])
def summarize_article():
    article = request.form.get('article')
    summary_type = request.form.get('summary_type')

    if summary_type == 'extractive':
        summary = summarize_text(article)
    else:
        summary = abstractive_summarize_text(article)

    return jsonify({'summary': summary})

# Updated HTML template to include summarization and categorization
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <div class="list-group-item">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="summarizeArticle('${article.content}')">Summarize</button>
                                <div class="summary mt-2" id="summary-${article.title}"></div>
                            </div>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });

        function summarizeArticle(article) {
            const summaryType = 'extractive';  // or 'abstractive'
            $.post('/summarize_article', { article: article, summary_type: summaryType }, function(data) {
                $('#summary-' + article.title).html('<p>' + data.summary + '</p>');
            });
        }
    </script>
</body>
</html>

En esta plantilla actualizada, añadimos botones para resumir cada artículo. La función summarizeArticle envía una solicitud al endpoint /summarize_article y muestra el resumen dentro de la página.

12.4.4 Categorización de Artículos

Integraremos la funcionalidad de categorización para categorizar automáticamente los artículos de noticias en diferentes temas.

nlp_engine.py (continuación):

# Define function to categorize article
def categorize_article(article):
    bow = dictionary.doc2bow(nltk.word_tokenize(article.lower()))
    topics = lda_model.get_document_topics(bow)
    sorted_topics = sorted(topics, key=lambda x: x[1], reverse=True)
    topic_index = sorted_topics[0][0]
    topic_terms = lda_model.show_topic(topic_index, topn=4)
    topic_keywords = [term[0] for term in topic_terms]
    return topic_keywords

Esta función utiliza el modelo LDA entrenado para categorizar el artículo en temas basados en las palabras clave más relevantes.

Aplicación Flask Actualizada:

@app.route('/categorize_article', methods=['POST'])
def categorize_article_route():
    article = request.form.get('article')
    category = categorize_article(article)
    return jsonify({'category': category})

# HTML template for categorizing articles
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,

 initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <div class="list-group-item">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="categorizeArticle('${article.content}')">Categorize</button>
                                <div class="category mt-2" id="category-${article.title}"></div>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="summarizeArticle('${article.content}')">Summarize</button>
                                <div class="summary mt-2" id="summary-${article.title}"></div>
                            </div>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });

        function summarizeArticle(article) {
            const summaryType = 'extractive';  // or 'abstractive'
            $.post('/summarize_article', { article: article, summary_type: summaryType }, function(data) {
                $('#summary-' + article.title).html('<p>' + data.summary + '</p>');
            });
        }

        function categorizeArticle(article) {
            $.post('/categorize_article', { article: article }, function(data) {
                $('#category-' + article.title).html('<p>' + data.category.join(', ') + '</p>');
            });
        }
    </script>
</body>
</html>

En esta plantilla actualizada, añadimos botones para categorizar cada artículo. La función categorizeArticle envía una solicitud al endpoint /categorize_article y muestra la categoría dentro de la página.

En esta sección, construimos la interfaz de usuario para el chatbot agregador de noticias. Utilizamos Flask para crear una interfaz web, permitiendo a los usuarios solicitar actualizaciones de noticias, ver resúmenes y categorizar artículos de noticias.

Creamos plantillas HTML con Bootstrap para un diseño receptivo y visualmente atractivo. El frontend interactúa con el backend para obtener artículos de noticias, resumirlos y categorizarlos en diferentes temas.

12.4 Construcción de la Interfaz de Usuario

En esta sección, nos centraremos en la construcción de la interfaz de usuario (UI) para el chatbot agregador de noticias. La UI es crucial ya que permite a los usuarios interactuar con el chatbot y acceder a los artículos de noticias. Crearemos una interfaz web utilizando Flask, un marco web ligero para Python. Esta interfaz permitirá a los usuarios solicitar actualizaciones de noticias, ver resúmenes y explorar artículos de noticias categorizados.

12.4.1 Configuración de Flask

Primero, necesitamos instalar Flask si aún no lo hemos hecho:

pip install Flask

A continuación, configuremos la estructura básica de nuestra aplicación Flask.

app.py:

from flask import Flask, request, jsonify, render_template
from nlp_engine import preprocess_text, categorize_article
from summarizer import summarize_text, abstractive_summarize_text
from news_fetcher import fetch_news

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

@app.route('/get_news', methods=['POST'])
def get_news():
    category = request.form.get('category')
    articles = fetch_news(category)
    return jsonify(articles)

@app.route('/summarize', methods=['POST'])
def summarize():
    article = request.form.get('article')
    summary_type = request.form.get('summary_type')

    if summary_type == 'extractive':
        summary = summarize_text(article)
    else:
        summary = abstractive_summarize_text(article)

    return jsonify({'summary': summary})

if __name__ == '__main__':
    app.run(debug=True)

En este script, definimos las rutas básicas para nuestra aplicación Flask:

  • La ruta home renderiza la página de inicio.
  • La ruta get_news obtiene artículos de noticias basados en la categoría seleccionada.
  • La ruta summarize resume un artículo dado utilizando ya sea el resumen extractivo o el abstractivo.

12.4.2 Creación de Plantillas HTML

A continuación, crearemos plantillas HTML para renderizar las páginas web. Usaremos Bootstrap para el diseño y así crear una interfaz visualmente atractiva y receptiva.

templates/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <a href="${article.url}" target="_blank" class="list-group-item list-group-item-action">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                            </a>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });
    </script>
</body>
</html>

En esta plantilla HTML, creamos un formulario simple para seleccionar la categoría de noticias y un div para mostrar los artículos de noticias obtenidos. Usamos jQuery para manejar el envío del formulario y actualizar dinámicamente la página con los artículos de noticias obtenidos.

12.4.3 Integración de Resumen y Categorización

Para permitir a los usuarios ver resúmenes y categorizar artículos, necesitamos agregar funcionalidad adicional tanto en el frontend como en el backend.

app.py (continuación):

@app.route('/categorize', methods=['POST'])
def categorize():
    article = request.form.get('article')
    category = categorize_article(article)
    return jsonify({'category': category})

@app.route('/summarize_article', methods=['POST'])
def summarize_article():
    article = request.form.get('article')
    summary_type = request.form.get('summary_type')

    if summary_type == 'extractive':
        summary = summarize_text(article)
    else:
        summary = abstractive_summarize_text(article)

    return jsonify({'summary': summary})

# Updated HTML template to include summarization and categorization
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <div class="list-group-item">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="summarizeArticle('${article.content}')">Summarize</button>
                                <div class="summary mt-2" id="summary-${article.title}"></div>
                            </div>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });

        function summarizeArticle(article) {
            const summaryType = 'extractive';  // or 'abstractive'
            $.post('/summarize_article', { article: article, summary_type: summaryType }, function(data) {
                $('#summary-' + article.title).html('<p>' + data.summary + '</p>');
            });
        }
    </script>
</body>
</html>

En esta plantilla actualizada, añadimos botones para resumir cada artículo. La función summarizeArticle envía una solicitud al endpoint /summarize_article y muestra el resumen dentro de la página.

12.4.4 Categorización de Artículos

Integraremos la funcionalidad de categorización para categorizar automáticamente los artículos de noticias en diferentes temas.

nlp_engine.py (continuación):

# Define function to categorize article
def categorize_article(article):
    bow = dictionary.doc2bow(nltk.word_tokenize(article.lower()))
    topics = lda_model.get_document_topics(bow)
    sorted_topics = sorted(topics, key=lambda x: x[1], reverse=True)
    topic_index = sorted_topics[0][0]
    topic_terms = lda_model.show_topic(topic_index, topn=4)
    topic_keywords = [term[0] for term in topic_terms]
    return topic_keywords

Esta función utiliza el modelo LDA entrenado para categorizar el artículo en temas basados en las palabras clave más relevantes.

Aplicación Flask Actualizada:

@app.route('/categorize_article', methods=['POST'])
def categorize_article_route():
    article = request.form.get('article')
    category = categorize_article(article)
    return jsonify({'category': category})

# HTML template for categorizing articles
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,

 initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <div class="list-group-item">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="categorizeArticle('${article.content}')">Categorize</button>
                                <div class="category mt-2" id="category-${article.title}"></div>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="summarizeArticle('${article.content}')">Summarize</button>
                                <div class="summary mt-2" id="summary-${article.title}"></div>
                            </div>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });

        function summarizeArticle(article) {
            const summaryType = 'extractive';  // or 'abstractive'
            $.post('/summarize_article', { article: article, summary_type: summaryType }, function(data) {
                $('#summary-' + article.title).html('<p>' + data.summary + '</p>');
            });
        }

        function categorizeArticle(article) {
            $.post('/categorize_article', { article: article }, function(data) {
                $('#category-' + article.title).html('<p>' + data.category.join(', ') + '</p>');
            });
        }
    </script>
</body>
</html>

En esta plantilla actualizada, añadimos botones para categorizar cada artículo. La función categorizeArticle envía una solicitud al endpoint /categorize_article y muestra la categoría dentro de la página.

En esta sección, construimos la interfaz de usuario para el chatbot agregador de noticias. Utilizamos Flask para crear una interfaz web, permitiendo a los usuarios solicitar actualizaciones de noticias, ver resúmenes y categorizar artículos de noticias.

Creamos plantillas HTML con Bootstrap para un diseño receptivo y visualmente atractivo. El frontend interactúa con el backend para obtener artículos de noticias, resumirlos y categorizarlos en diferentes temas.

12.4 Construcción de la Interfaz de Usuario

En esta sección, nos centraremos en la construcción de la interfaz de usuario (UI) para el chatbot agregador de noticias. La UI es crucial ya que permite a los usuarios interactuar con el chatbot y acceder a los artículos de noticias. Crearemos una interfaz web utilizando Flask, un marco web ligero para Python. Esta interfaz permitirá a los usuarios solicitar actualizaciones de noticias, ver resúmenes y explorar artículos de noticias categorizados.

12.4.1 Configuración de Flask

Primero, necesitamos instalar Flask si aún no lo hemos hecho:

pip install Flask

A continuación, configuremos la estructura básica de nuestra aplicación Flask.

app.py:

from flask import Flask, request, jsonify, render_template
from nlp_engine import preprocess_text, categorize_article
from summarizer import summarize_text, abstractive_summarize_text
from news_fetcher import fetch_news

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

@app.route('/get_news', methods=['POST'])
def get_news():
    category = request.form.get('category')
    articles = fetch_news(category)
    return jsonify(articles)

@app.route('/summarize', methods=['POST'])
def summarize():
    article = request.form.get('article')
    summary_type = request.form.get('summary_type')

    if summary_type == 'extractive':
        summary = summarize_text(article)
    else:
        summary = abstractive_summarize_text(article)

    return jsonify({'summary': summary})

if __name__ == '__main__':
    app.run(debug=True)

En este script, definimos las rutas básicas para nuestra aplicación Flask:

  • La ruta home renderiza la página de inicio.
  • La ruta get_news obtiene artículos de noticias basados en la categoría seleccionada.
  • La ruta summarize resume un artículo dado utilizando ya sea el resumen extractivo o el abstractivo.

12.4.2 Creación de Plantillas HTML

A continuación, crearemos plantillas HTML para renderizar las páginas web. Usaremos Bootstrap para el diseño y así crear una interfaz visualmente atractiva y receptiva.

templates/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <a href="${article.url}" target="_blank" class="list-group-item list-group-item-action">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                            </a>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });
    </script>
</body>
</html>

En esta plantilla HTML, creamos un formulario simple para seleccionar la categoría de noticias y un div para mostrar los artículos de noticias obtenidos. Usamos jQuery para manejar el envío del formulario y actualizar dinámicamente la página con los artículos de noticias obtenidos.

12.4.3 Integración de Resumen y Categorización

Para permitir a los usuarios ver resúmenes y categorizar artículos, necesitamos agregar funcionalidad adicional tanto en el frontend como en el backend.

app.py (continuación):

@app.route('/categorize', methods=['POST'])
def categorize():
    article = request.form.get('article')
    category = categorize_article(article)
    return jsonify({'category': category})

@app.route('/summarize_article', methods=['POST'])
def summarize_article():
    article = request.form.get('article')
    summary_type = request.form.get('summary_type')

    if summary_type == 'extractive':
        summary = summarize_text(article)
    else:
        summary = abstractive_summarize_text(article)

    return jsonify({'summary': summary})

# Updated HTML template to include summarization and categorization
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <div class="list-group-item">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="summarizeArticle('${article.content}')">Summarize</button>
                                <div class="summary mt-2" id="summary-${article.title}"></div>
                            </div>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });

        function summarizeArticle(article) {
            const summaryType = 'extractive';  // or 'abstractive'
            $.post('/summarize_article', { article: article, summary_type: summaryType }, function(data) {
                $('#summary-' + article.title).html('<p>' + data.summary + '</p>');
            });
        }
    </script>
</body>
</html>

En esta plantilla actualizada, añadimos botones para resumir cada artículo. La función summarizeArticle envía una solicitud al endpoint /summarize_article y muestra el resumen dentro de la página.

12.4.4 Categorización de Artículos

Integraremos la funcionalidad de categorización para categorizar automáticamente los artículos de noticias en diferentes temas.

nlp_engine.py (continuación):

# Define function to categorize article
def categorize_article(article):
    bow = dictionary.doc2bow(nltk.word_tokenize(article.lower()))
    topics = lda_model.get_document_topics(bow)
    sorted_topics = sorted(topics, key=lambda x: x[1], reverse=True)
    topic_index = sorted_topics[0][0]
    topic_terms = lda_model.show_topic(topic_index, topn=4)
    topic_keywords = [term[0] for term in topic_terms]
    return topic_keywords

Esta función utiliza el modelo LDA entrenado para categorizar el artículo en temas basados en las palabras clave más relevantes.

Aplicación Flask Actualizada:

@app.route('/categorize_article', methods=['POST'])
def categorize_article_route():
    article = request.form.get('article')
    category = categorize_article(article)
    return jsonify({'category': category})

# HTML template for categorizing articles
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,

 initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <div class="list-group-item">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="categorizeArticle('${article.content}')">Categorize</button>
                                <div class="category mt-2" id="category-${article.title}"></div>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="summarizeArticle('${article.content}')">Summarize</button>
                                <div class="summary mt-2" id="summary-${article.title}"></div>
                            </div>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });

        function summarizeArticle(article) {
            const summaryType = 'extractive';  // or 'abstractive'
            $.post('/summarize_article', { article: article, summary_type: summaryType }, function(data) {
                $('#summary-' + article.title).html('<p>' + data.summary + '</p>');
            });
        }

        function categorizeArticle(article) {
            $.post('/categorize_article', { article: article }, function(data) {
                $('#category-' + article.title).html('<p>' + data.category.join(', ') + '</p>');
            });
        }
    </script>
</body>
</html>

En esta plantilla actualizada, añadimos botones para categorizar cada artículo. La función categorizeArticle envía una solicitud al endpoint /categorize_article y muestra la categoría dentro de la página.

En esta sección, construimos la interfaz de usuario para el chatbot agregador de noticias. Utilizamos Flask para crear una interfaz web, permitiendo a los usuarios solicitar actualizaciones de noticias, ver resúmenes y categorizar artículos de noticias.

Creamos plantillas HTML con Bootstrap para un diseño receptivo y visualmente atractivo. El frontend interactúa con el backend para obtener artículos de noticias, resumirlos y categorizarlos en diferentes temas.

12.4 Construcción de la Interfaz de Usuario

En esta sección, nos centraremos en la construcción de la interfaz de usuario (UI) para el chatbot agregador de noticias. La UI es crucial ya que permite a los usuarios interactuar con el chatbot y acceder a los artículos de noticias. Crearemos una interfaz web utilizando Flask, un marco web ligero para Python. Esta interfaz permitirá a los usuarios solicitar actualizaciones de noticias, ver resúmenes y explorar artículos de noticias categorizados.

12.4.1 Configuración de Flask

Primero, necesitamos instalar Flask si aún no lo hemos hecho:

pip install Flask

A continuación, configuremos la estructura básica de nuestra aplicación Flask.

app.py:

from flask import Flask, request, jsonify, render_template
from nlp_engine import preprocess_text, categorize_article
from summarizer import summarize_text, abstractive_summarize_text
from news_fetcher import fetch_news

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

@app.route('/get_news', methods=['POST'])
def get_news():
    category = request.form.get('category')
    articles = fetch_news(category)
    return jsonify(articles)

@app.route('/summarize', methods=['POST'])
def summarize():
    article = request.form.get('article')
    summary_type = request.form.get('summary_type')

    if summary_type == 'extractive':
        summary = summarize_text(article)
    else:
        summary = abstractive_summarize_text(article)

    return jsonify({'summary': summary})

if __name__ == '__main__':
    app.run(debug=True)

En este script, definimos las rutas básicas para nuestra aplicación Flask:

  • La ruta home renderiza la página de inicio.
  • La ruta get_news obtiene artículos de noticias basados en la categoría seleccionada.
  • La ruta summarize resume un artículo dado utilizando ya sea el resumen extractivo o el abstractivo.

12.4.2 Creación de Plantillas HTML

A continuación, crearemos plantillas HTML para renderizar las páginas web. Usaremos Bootstrap para el diseño y así crear una interfaz visualmente atractiva y receptiva.

templates/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <a href="${article.url}" target="_blank" class="list-group-item list-group-item-action">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                            </a>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });
    </script>
</body>
</html>

En esta plantilla HTML, creamos un formulario simple para seleccionar la categoría de noticias y un div para mostrar los artículos de noticias obtenidos. Usamos jQuery para manejar el envío del formulario y actualizar dinámicamente la página con los artículos de noticias obtenidos.

12.4.3 Integración de Resumen y Categorización

Para permitir a los usuarios ver resúmenes y categorizar artículos, necesitamos agregar funcionalidad adicional tanto en el frontend como en el backend.

app.py (continuación):

@app.route('/categorize', methods=['POST'])
def categorize():
    article = request.form.get('article')
    category = categorize_article(article)
    return jsonify({'category': category})

@app.route('/summarize_article', methods=['POST'])
def summarize_article():
    article = request.form.get('article')
    summary_type = request.form.get('summary_type')

    if summary_type == 'extractive':
        summary = summarize_text(article)
    else:
        summary = abstractive_summarize_text(article)

    return jsonify({'summary': summary})

# Updated HTML template to include summarization and categorization
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <div class="list-group-item">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="summarizeArticle('${article.content}')">Summarize</button>
                                <div class="summary mt-2" id="summary-${article.title}"></div>
                            </div>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });

        function summarizeArticle(article) {
            const summaryType = 'extractive';  // or 'abstractive'
            $.post('/summarize_article', { article: article, summary_type: summaryType }, function(data) {
                $('#summary-' + article.title).html('<p>' + data.summary + '</p>');
            });
        }
    </script>
</body>
</html>

En esta plantilla actualizada, añadimos botones para resumir cada artículo. La función summarizeArticle envía una solicitud al endpoint /summarize_article y muestra el resumen dentro de la página.

12.4.4 Categorización de Artículos

Integraremos la funcionalidad de categorización para categorizar automáticamente los artículos de noticias en diferentes temas.

nlp_engine.py (continuación):

# Define function to categorize article
def categorize_article(article):
    bow = dictionary.doc2bow(nltk.word_tokenize(article.lower()))
    topics = lda_model.get_document_topics(bow)
    sorted_topics = sorted(topics, key=lambda x: x[1], reverse=True)
    topic_index = sorted_topics[0][0]
    topic_terms = lda_model.show_topic(topic_index, topn=4)
    topic_keywords = [term[0] for term in topic_terms]
    return topic_keywords

Esta función utiliza el modelo LDA entrenado para categorizar el artículo en temas basados en las palabras clave más relevantes.

Aplicación Flask Actualizada:

@app.route('/categorize_article', methods=['POST'])
def categorize_article_route():
    article = request.form.get('article')
    category = categorize_article(article)
    return jsonify({'category': category})

# HTML template for categorizing articles
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,

 initial-scale=1.0">
    <title>News Aggregator Chatbot</title>
    <link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
    <div class="container">
        <h1 class="mt-5">News Aggregator Chatbot</h1>
        <form id="news-form" class="mt-4">
            <div class="form-group">
                <label for="category">Select News Category</label>
                <select class="form-control" id="category" name="category">
                    <option value="general">General</option>
                    <option value="business">Business</option>
                    <option value="technology">Technology</option>
                    <option value="sports">Sports</option>
                    <option value="entertainment">Entertainment</option>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">Get News</button>
        </form>
        <div id="news-articles" class="mt-4"></div>
    </div>

    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
    <script>
        $(document).ready(function() {
            $('#news-form').on('submit', function(event) {
                event.preventDefault();
                const category = $('#category').val();
                $.post('/get_news', { category: category }, function(data) {
                    let articlesHtml = '<div class="list-group">';
                    data.forEach(article => {
                        articlesHtml += `
                            <div class="list-group-item">
                                <h5 class="mb-1">${article.title}</h5>
                                <p class="mb-1">${article.description}</p>
                                <small>${article.source} - ${article.publishedAt}</small>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="categorizeArticle('${article.content}')">Categorize</button>
                                <div class="category mt-2" id="category-${article.title}"></div>
                                <button class="btn btn-secondary btn-sm mt-2" onclick="summarizeArticle('${article.content}')">Summarize</button>
                                <div class="summary mt-2" id="summary-${article.title}"></div>
                            </div>
                        `;
                    });
                    articlesHtml += '</div>';
                    $('#news-articles').html(articlesHtml);
                });
            });
        });

        function summarizeArticle(article) {
            const summaryType = 'extractive';  // or 'abstractive'
            $.post('/summarize_article', { article: article, summary_type: summaryType }, function(data) {
                $('#summary-' + article.title).html('<p>' + data.summary + '</p>');
            });
        }

        function categorizeArticle(article) {
            $.post('/categorize_article', { article: article }, function(data) {
                $('#category-' + article.title).html('<p>' + data.category.join(', ') + '</p>');
            });
        }
    </script>
</body>
</html>

En esta plantilla actualizada, añadimos botones para categorizar cada artículo. La función categorizeArticle envía una solicitud al endpoint /categorize_article y muestra la categoría dentro de la página.

En esta sección, construimos la interfaz de usuario para el chatbot agregador de noticias. Utilizamos Flask para crear una interfaz web, permitiendo a los usuarios solicitar actualizaciones de noticias, ver resúmenes y categorizar artículos de noticias.

Creamos plantillas HTML con Bootstrap para un diseño receptivo y visualmente atractivo. El frontend interactúa con el backend para obtener artículos de noticias, resumirlos y categorizarlos en diferentes temas.