Spaces:
Runtime error
Runtime error
Upload app.py
Browse files
app.py
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import plotly.express as px
|
3 |
+
import pandas as pd
|
4 |
+
from wordcloud import WordCloud
|
5 |
+
import matplotlib.pyplot as plt
|
6 |
+
from scrapper_rss import Scrapper
|
7 |
+
import datetime as dt
|
8 |
+
|
9 |
+
st.set_option('deprecation.showPyplotGlobalUse', False)
|
10 |
+
|
11 |
+
scrapper = Scrapper()
|
12 |
+
|
13 |
+
noticias = pd.read_csv('./diarios/diarios_historicos.csv')
|
14 |
+
noticias=noticias.drop('descripcion' ,axis=1)
|
15 |
+
fechas = pd.read_csv('./fechas.csv')
|
16 |
+
|
17 |
+
diarios = list(noticias.diario.unique())
|
18 |
+
secciones = list(noticias.seccion.unique())
|
19 |
+
columna_para_nube = ['titulo', 'descripcion']
|
20 |
+
|
21 |
+
st.set_page_config(
|
22 |
+
page_title="Observatorio de noticias",
|
23 |
+
initial_sidebar_state="expanded"
|
24 |
+
)
|
25 |
+
|
26 |
+
|
27 |
+
with st.sidebar:
|
28 |
+
st.write("Creado por [sebasur90](https://www.linkedin.com/in/sebastian-rodriguez-9b417830/)")
|
29 |
+
|
30 |
+
diarios_select = st.multiselect('Selecciona los diarios',
|
31 |
+
diarios, default=diarios)
|
32 |
+
secciones_select = st.multiselect('Selecciona las secciones',
|
33 |
+
secciones, default=secciones)
|
34 |
+
palabra_buscada = st.text_input('Buscar palabra', 'Ninguna')
|
35 |
+
|
36 |
+
if st.button('Actualizar Diarios'):
|
37 |
+
dia_str = str(dt.datetime.today().date())
|
38 |
+
if fechas.iloc[-1]['dia'] == dia_str:
|
39 |
+
st.success("Las noticias ya estan actualizadas")
|
40 |
+
pass
|
41 |
+
else:
|
42 |
+
with st.spinner('Actualizando los siguientes diarios..'):
|
43 |
+
scrapper.run()
|
44 |
+
st.write("Se actualizaron las noticias")
|
45 |
+
|
46 |
+
|
47 |
+
|
48 |
+
|
49 |
+
if palabra_buscada == "Ninguna" or palabra_buscada == "":
|
50 |
+
st.title("Observatorio de Noticias")
|
51 |
+
st.write("""
|
52 |
+
|
53 |
+
Hola! Bienvenido a la aplicaci贸n de an谩lisis de sentimientos en las noticias. Esta aplicaci贸n extrae las noticias de algunos de los diarios mas
|
54 |
+
importantes del pa铆s ( a traves del RSS) y realiza un analisis de sentimientos sobre los titulos de cada una.
|
55 |
+
La app permite filtrar por palabra clave y generar una nube de palabras con los resultados
|
56 |
+
|
57 |
+
De acuerdo al sentimiento analizado sobre cada noticia encontraremos 3 grupos:
|
58 |
+
|
59 |
+
**Sentimiento Positivo:** "YPF aument贸 la distribuci贸n de gasoil y asegur贸 que el campo tiene garantizado el abastecimiento"
|
60 |
+
*Probabilidades: NEGATIVA=0.008 --- NEUTRA 0.43 --- POSITIVA 0.56 (GANADOR --> POSITIVA)*
|
61 |
+
|
62 |
+
|
63 |
+
**Sentimiento Neutro:** "El aeroclub de Comodoro Rivadavia celebr贸 su 87掳 aniversario"
|
64 |
+
*Probabilidades: NEGATIVA=0.02 --- NEUTRA 0.67 --- POSITIVA 0.30 (GANADOR --> NEUTRA)*
|
65 |
+
|
66 |
+
**Sentimiento Negativo:** "Crecen las expectativas de inflaci贸n del mercado"
|
67 |
+
*Probabilidades: NEGATIVA=0.60 --- NEUTRA 0.37 --- POSITIVA 0.15 (GANADOR --> NEGATIVA)*
|
68 |
+
|
69 |
+
""")
|
70 |
+
|
71 |
+
|
72 |
+
|
73 |
+
pass
|
74 |
+
else:
|
75 |
+
#st.title("Observatorio de Noticias")
|
76 |
+
st.header(f"Resultados para : {palabra_buscada}")
|
77 |
+
|
78 |
+
noticias = noticias[noticias['titulo'].str.contains(palabra_buscada)]
|
79 |
+
|
80 |
+
st.session_state['dataframe_filtrado'] = noticias[(noticias.diario.isin(
|
81 |
+
diarios_select)) & (noticias.seccion.isin(secciones_select))]
|
82 |
+
|
83 |
+
st.subheader("Muestra aleatoria de noticias")
|
84 |
+
st.dataframe(st.session_state['dataframe_filtrado'].sample(frac=1))
|
85 |
+
st.session_state['dataframe_agrupado'] = st.session_state['dataframe_filtrado'].groupby(
|
86 |
+
'diario')[['pond_negativos', 'pond_neutro', 'pond_positivo']].mean().reset_index()
|
87 |
+
|
88 |
+
fig = px.bar(st.session_state['dataframe_agrupado'], x="diario", y=['pond_neutro', "pond_negativos", 'pond_positivo'], text_auto=True,
|
89 |
+
title=f"Analisis de sentimientos para las noticias seleccionadas seg煤n el diario"
|
90 |
+
)
|
91 |
+
|
92 |
+
newnames = {'pond_neutro':'NEUTRAL', 'pond_negativos': 'NEGATIVA','pond_positivo': 'POSITIVA'}
|
93 |
+
fig.for_each_trace(lambda t: t.update(name = newnames[t.name],
|
94 |
+
legendgroup = newnames[t.name],
|
95 |
+
hovertemplate = t.hovertemplate.replace(t.name, newnames[t.name])
|
96 |
+
)
|
97 |
+
)
|
98 |
+
fig.update_layout(
|
99 |
+
xaxis_title="Diarios",
|
100 |
+
yaxis_title="Probabilidades (de 0 a 1)",
|
101 |
+
|
102 |
+
)
|
103 |
+
fig.update_layout(legend_title_text='Probabilidades')
|
104 |
+
|
105 |
+
st.plotly_chart(fig)
|
106 |
+
|
107 |
+
|
108 |
+
def transforma_letras_para_wordcloud(dataframe_noticias):
|
109 |
+
columna_analizada = list(dataframe_noticias['titulo'])
|
110 |
+
acentos = {'谩': 'a', '茅': 'e', '铆': 'i', '贸': 'o', '煤': 'u',
|
111 |
+
'脕': 'A', 'E': 'E', '脥': 'I', '脫': 'O', '脷': 'U'}
|
112 |
+
lista_palabras_para_wordcloud = []
|
113 |
+
for palabras in columna_analizada:
|
114 |
+
palabras_div = palabras.split(' ')
|
115 |
+
for letras in palabras_div:
|
116 |
+
for acen in acentos:
|
117 |
+
if acen in letras:
|
118 |
+
letras = letras.replace(acen, acentos[acen])
|
119 |
+
lista_palabras_para_wordcloud.append(letras.lower())
|
120 |
+
return ' '.join(lista_palabras_para_wordcloud)
|
121 |
+
|
122 |
+
|
123 |
+
def genera_wordcloud(dataframe_noticias):
|
124 |
+
palabras_para_wordcloud = transforma_letras_para_wordcloud(
|
125 |
+
dataframe_noticias)
|
126 |
+
palabras_ignoradas = set(['a', 'ante', 'con', 'contra', 'de', 'desde', 'durante', 'en', 'para', 'por', 'segun', 'sin', 'sobre', 'el', 'la', 'los', 'las',
|
127 |
+
'...', 'y', 'hoy', 'este', 'cuanto', 'un', 'del', 'las', 'que', 'con', 'todos', 'es', '驴qu茅', 'como', 'cada',
|
128 |
+
'jueves', '驴cuanto', 'hoy', 'al', 'cual', 'se', 'su', 'sus', 'lo', 'una', 'un', 'tiene',
|
129 |
+
'le', 'habia'])
|
130 |
+
|
131 |
+
wordcloud = WordCloud(width=1920, height=1080, stopwords=palabras_ignoradas).generate(
|
132 |
+
palabras_para_wordcloud)
|
133 |
+
plt.imshow(wordcloud, interpolation='bilinear')
|
134 |
+
plt.axis("off")
|
135 |
+
st.pyplot()
|
136 |
+
|
137 |
+
|
138 |
+
if st.button('Generar Nube'):
|
139 |
+
genera_wordcloud(st.session_state['dataframe_filtrado'])
|
140 |
+
else:
|
141 |
+
pass
|