Joshua1808 commited on
Commit
8255c77
1 Parent(s): ba85806

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -29
app.py CHANGED
@@ -8,17 +8,18 @@ import geopy
8
  import matplotlib.pyplot as plt
9
  import langdetect
10
 
11
-
12
- from pysentimiento.preprocessing import preprocess_tweet
13
  from geopy.geocoders import Nominatim
 
14
  from transformers import pipeline
 
15
  from langdetect import detect
16
 
17
 
18
  model_checkpoint = "hackathon-pln-es/twitter_sexismo-finetuned-robertuito-exist2021"
19
  pipeline_nlp = pipeline("text-classification", model=model_checkpoint)
20
 
21
-
22
  consumer_key = "BjipwQslVG4vBdy4qK318KnoA"
23
  consumer_secret = "3fzL70v9faklrPgvTi3zbofw9rwk92fgGdtAslFkFYt8kGmqBJ"
24
  access_token = "1217853705086799872-Y5zEChpTeKccuLY3XJRXDPPZhNrlba"
@@ -26,7 +27,8 @@ access_token_secret = "pqQ5aFSJxzJ2xnI6yhVtNjQO36FOu8DBOH6DtUrPAU54J"
26
  auth = tw.OAuthHandler(consumer_key, consumer_secret)
27
  auth.set_access_token(access_token, access_token_secret)
28
  api = tw.API(auth, wait_on_rate_limit=True)
29
-
 
30
  def limpieza_datos(tweet):
31
  # Eliminar emojis
32
  tweet = re.sub(r'[\U0001F600-\U0001F64F]', '', tweet)
@@ -44,6 +46,7 @@ def limpieza_datos(tweet):
44
  tweet = re.sub(r'[^a-zA-Z0-9 \n\áéíóúÁÉÍÓÚñÑ.]', '', tweet)
45
  return tweet
46
 
 
47
  def highlight_survived(s):
48
  return ['background-color: red']*len(s) if (s.Sexista == 1) else ['background-color: green']*len(s)
49
 
@@ -51,16 +54,11 @@ def color_survived(val):
51
  color = 'red' if val=='Sexista' else 'white'
52
  return f'background-color: {color}'
53
 
54
-
55
  st.set_page_config(layout="wide")
56
  st.markdown('<style>body{background-color: Blue;}</style>',unsafe_allow_html=True)
57
 
58
- #st.markdown('<style>body{background-color: Blue;}</style>',unsafe_allow_html=True)
59
  #colT1,colT2 = st.columns([2,8])
60
- st.markdown(""" <style> .fondo {
61
- background-image: url("https://www.google.com/url?sa=i&url=https%3A%2F%2Flasmujereseneldeportemexicano.wordpress.com%2F2016%2F11%2F17%2Fpor-que-es-importante-hablar-de-genero%2F&psig=AOvVaw0xG7SVXtJoEpwt-fF5Kykt&ust=1676431557056000&source=images&cd=vfe&ved=0CBAQjRxqFwoTCJiu-a6IlP0CFQAAAAAdAAAAABAJ");
62
- background-size: 180%;}
63
- </style> """, unsafe_allow_html=True)
64
 
65
 
66
  st.markdown(""" <style> .font {
@@ -70,7 +68,7 @@ font-size:40px ; font-family: 'Cooper Black'; color: #301E67;}
70
  #st.markdown('<p class="font"; style="text-align: center;>Análisis de comentarios sexistas en linea</p>', unsafe_allow_html=True)
71
  st.markdown('<p class="font" style="text-align: center;">Detectando el Sexismo en Linea: Un proyecto de Investigación</p>', unsafe_allow_html=True)
72
 
73
-
74
  st.markdown(""" <style> .font1 {
75
  font-size:28px ; font-family: 'Times New Roman'; color: #8d33ff;}
76
  </style> """, unsafe_allow_html=True)
@@ -79,85 +77,104 @@ st.markdown(""" <style> .font2 {
79
  font-size:18px ; font-family: 'Times New Roman'; color: #5B8FB9;}
80
  </style> """, unsafe_allow_html=True)
81
 
 
82
  st.markdown('<p class="font2">Este proyecto consiste en una aplicación web que utiliza la biblioteca Tweepy de Python para descargar tweets de Twitter, permitiendo buscar Tweets por usuario y por localidad. Luego, utiliza modelos de lenguaje basados en Transformers para analizar los tweets y detectar comentarios y determinar si son "Sexistas" o "No Sexistas". El proyecto busca identificar y combatir el discurso sexista en línea para promover la igualdad de género y la inclusión.</p>',unsafe_allow_html=True)
83
 
84
-
85
  def tweets_usuario(usuario, cant_de_tweets):
86
- tabla = []
87
  if(cant_de_tweets > 0 and usuario != "" ):
88
  try:
89
  # Buscar la información del perfil de usuario
90
  user = api.get_user(screen_name=usuario)
 
91
  tweets = api.user_timeline(screen_name = usuario,tweet_mode="extended", count= cant_de_tweets)
92
- result = []
 
93
  for tweet in tweets:
 
94
  if (tweet.full_text.startswith('RT')):
95
  continue
96
  else:
97
  text = tweet.full_text
 
98
  try:
99
  language = detect(text)
100
  if language == 'es':
 
101
  datos=limpieza_datos(text)
102
  if datos == "":
103
  continue
104
  else:
 
105
  prediction = pipeline_nlp(datos)
106
  for predic in prediction:
 
107
  etiqueta = {'Tweets': datos, 'Prediccion': predic['label'], 'Probabilidad': predic['score']}
108
  result.append(etiqueta)
109
  except:
110
  pass
 
111
  df = pd.DataFrame(result)
 
112
  if df.empty:
113
  muestra= st.text("No hay tweets Sexistas a analizar")
114
  tabla.append(muestra)
 
115
  else:
 
116
  df.sort_values(by=['Prediccion', 'Probabilidad'], ascending=[False, False], inplace=True)
117
  df['Prediccion'] = np.where(df['Prediccion'] == 'LABEL_1', 'Sexista', 'No Sexista')
118
  df['Probabilidad'] = df['Probabilidad'].apply(lambda x: round(x, 3))
119
  muestra = st.table(df.reset_index(drop=True).head(50).style.applymap(color_survived, subset=['Prediccion']))
120
- if len(df) > 10:
121
- # Agregar una barra de desplazamiento vertical a la tabla
122
- muestra._parent.markdown(f'<style>.dataframe .data {{height: 300px; overflow: scroll}}</style>', unsafe_allow_html=True)
123
  tabla.append(muestra)
124
  except Exception as e:
 
125
  muestra = st.text(f"La cuenta {usuario} no existe.")
126
  tabla.append(muestra)
127
  else:
 
128
  muestra= st.text("Ingrese los parametros correspondientes")
129
  tabla.append(muestra)
130
  return tabla
131
 
132
-
133
  def tweets_localidad(buscar_localidad):
134
- tabla = []
135
  try:
 
136
  geolocator = Nominatim(user_agent="nombre_del_usuario")
137
  location = geolocator.geocode(buscar_localidad)
138
- radius = "15km"
 
139
  tweets = api.search_tweets(q="",lang="es",geocode=f"{location.latitude},{location.longitude},{radius}", count = 100, tweet_mode="extended")
140
- result = []
 
141
  for tweet in tweets:
 
142
  if (tweet.full_text.startswith('RT')):
143
  continue
144
  elif not tweet.full_text.strip():
145
  continue
146
  else:
 
147
  datos = limpieza_datos(tweet.full_text)
148
  prediction = pipeline_nlp(datos)
149
  for predic in prediction:
 
150
  etiqueta = {'Tweets': datos,'Prediccion': predic['label'], 'Probabilidad': predic['score']}
151
  result.append(etiqueta)
 
152
  df = pd.DataFrame(result)
 
153
  if df.empty:
154
  muestra=st.text("No se encontraron tweets sexistas dentro de la localidad")
155
  tabla.append(muestra)
156
  else:
157
  #tabla.append(muestra)
 
158
  df.sort_values(by=['Prediccion', 'Probabilidad'], ascending=[False, False], inplace=True)
159
- #df.sort_values(by='Probabilidad', ascending=False, inplace=True)
160
- #df.sort_values(by='Prediccion', ascending=False, inplace=True)
161
  df['Prediccion'] = np.where(df['Prediccion'] == 'LABEL_1', 'Sexista', 'No Sexista')
162
  df['Probabilidad'] = df['Probabilidad'].round(3)
163
  # Obtener los datos con probabilidad mayor a 0.50
@@ -172,13 +189,14 @@ def tweets_localidad(buscar_localidad):
172
  muestra_df = pd.concat([sexista_df, no_sexista_df], axis=0)
173
  col1, col2 = st.columns(2)
174
  with col1:
 
175
  muestra = st.table(muestra_df.reset_index(drop=True).head(6).style.applymap(color_survived, subset=['Prediccion']))
176
  with col2:
177
  resultado = df['Prediccion'].value_counts()
178
  def autopct_fun(abs_values):
179
  gen = iter(abs_values)
180
  return lambda pct: f"{pct:.1f}% ({next(gen)})"
181
-
182
  colores=["#aae977","#EE3555"]
183
  fig, ax = plt.subplots()
184
  fig.set_size_inches(2,2)
@@ -216,19 +234,26 @@ def analizar_frase(frase):
216
  tabla = st.text("Solo Frase en español")
217
 
218
  return tabla
219
-
 
220
  def run():
221
- #col1, col2 = st.columns(2)
222
  with st.form("my_form"):
 
223
  search_words = st.text_input("Introduzca la frase, el usuario o localidad para analizar y pulse el check correspondiente")
 
224
  number_of_tweets = st.number_input('Introduzca número de tweets a analizar del usuario Máximo 50', 0,50,0)
225
  st.write("Escoja una Opción:")
 
226
  termino=st.checkbox('Frase')
227
  usuario=st.checkbox('Usuario')
228
  localidad=st.checkbox('Localidad')
 
229
  submit_button = st.form_submit_button(label='Analizar')
 
230
  error =False
231
-
 
232
  if submit_button:
233
  # Condición para el caso de que esten dos check seleccionados
234
  if ( termino == False and usuario == False and localidad == False):
@@ -237,7 +262,8 @@ def run():
237
  elif ( termino == True and usuario == True and localidad == True):
238
  st.text('Error se han seleccionado varios check')
239
  error=True
240
-
 
241
  if (error == False):
242
  if (termino):
243
  analizar_frase(search_words)
@@ -245,5 +271,6 @@ def run():
245
  tweets_usuario(search_words,number_of_tweets)
246
  elif (localidad):
247
  tweets_localidad(search_words)
248
-
 
249
  run()
 
8
  import matplotlib.pyplot as plt
9
  import langdetect
10
 
11
+ #Importar Nominatim para geocalización
 
12
  from geopy.geocoders import Nominatim
13
+ #Importar pipeline para usar al modelo Transformer
14
  from transformers import pipeline
15
+ #Importar detec para el idioma, e
16
  from langdetect import detect
17
 
18
 
19
  model_checkpoint = "hackathon-pln-es/twitter_sexismo-finetuned-robertuito-exist2021"
20
  pipeline_nlp = pipeline("text-classification", model=model_checkpoint)
21
 
22
+ #Claves de acceso a la API de Twitter
23
  consumer_key = "BjipwQslVG4vBdy4qK318KnoA"
24
  consumer_secret = "3fzL70v9faklrPgvTi3zbofw9rwk92fgGdtAslFkFYt8kGmqBJ"
25
  access_token = "1217853705086799872-Y5zEChpTeKccuLY3XJRXDPPZhNrlba"
 
27
  auth = tw.OAuthHandler(consumer_key, consumer_secret)
28
  auth.set_access_token(access_token, access_token_secret)
29
  api = tw.API(auth, wait_on_rate_limit=True)
30
+
31
+ #Función para limpiar datos
32
  def limpieza_datos(tweet):
33
  # Eliminar emojis
34
  tweet = re.sub(r'[\U0001F600-\U0001F64F]', '', tweet)
 
46
  tweet = re.sub(r'[^a-zA-Z0-9 \n\áéíóúÁÉÍÓÚñÑ.]', '', tweet)
47
  return tweet
48
 
49
+ #Función para cambiar el color de la palabra "Sexista"
50
  def highlight_survived(s):
51
  return ['background-color: red']*len(s) if (s.Sexista == 1) else ['background-color: green']*len(s)
52
 
 
54
  color = 'red' if val=='Sexista' else 'white'
55
  return f'background-color: {color}'
56
 
57
+ #Función para el ancho de la pagina web
58
  st.set_page_config(layout="wide")
59
  st.markdown('<style>body{background-color: Blue;}</style>',unsafe_allow_html=True)
60
 
 
61
  #colT1,colT2 = st.columns([2,8])
 
 
 
 
62
 
63
 
64
  st.markdown(""" <style> .font {
 
68
  #st.markdown('<p class="font"; style="text-align: center;>Análisis de comentarios sexistas en linea</p>', unsafe_allow_html=True)
69
  st.markdown('<p class="font" style="text-align: center;">Detectando el Sexismo en Linea: Un proyecto de Investigación</p>', unsafe_allow_html=True)
70
 
71
+ #Editar el tipo de letra
72
  st.markdown(""" <style> .font1 {
73
  font-size:28px ; font-family: 'Times New Roman'; color: #8d33ff;}
74
  </style> """, unsafe_allow_html=True)
 
77
  font-size:18px ; font-family: 'Times New Roman'; color: #5B8FB9;}
78
  </style> """, unsafe_allow_html=True)
79
 
80
+ #Parrafo
81
  st.markdown('<p class="font2">Este proyecto consiste en una aplicación web que utiliza la biblioteca Tweepy de Python para descargar tweets de Twitter, permitiendo buscar Tweets por usuario y por localidad. Luego, utiliza modelos de lenguaje basados en Transformers para analizar los tweets y detectar comentarios y determinar si son "Sexistas" o "No Sexistas". El proyecto busca identificar y combatir el discurso sexista en línea para promover la igualdad de género y la inclusión.</p>',unsafe_allow_html=True)
82
 
83
+ #Función para extrer tweets de usuarios de Twitter, y analizarlos por el modelo Transformer
84
  def tweets_usuario(usuario, cant_de_tweets):
85
+ tabla = [] # crea una lista vacía llamada tabla
86
  if(cant_de_tweets > 0 and usuario != "" ):
87
  try:
88
  # Buscar la información del perfil de usuario
89
  user = api.get_user(screen_name=usuario)
90
+ # utiliza la API de Twitter para buscar tweets en español de un usuario de Twitter
91
  tweets = api.user_timeline(screen_name = usuario,tweet_mode="extended", count= cant_de_tweets)
92
+ result = [] # crea una lista vacía llamada result
93
+ # itera a través de cada tweet en la lista de tweets encontrados
94
  for tweet in tweets:
95
+ # si el tweet comienza con 'RT' o si el tweet está vacío, continúa con el siguiente tweet
96
  if (tweet.full_text.startswith('RT')):
97
  continue
98
  else:
99
  text = tweet.full_text
100
+ #Try Catch para detectar que sean del idioma español
101
  try:
102
  language = detect(text)
103
  if language == 'es':
104
+ #Limpieza de cada tweet extraido
105
  datos=limpieza_datos(text)
106
  if datos == "":
107
  continue
108
  else:
109
+ #Predicción del modelo Transformer para cada tweet
110
  prediction = pipeline_nlp(datos)
111
  for predic in prediction:
112
+ # Agrega la etiqueta de Tweets, Predicción y Probabilidad en una lista y la agrega a la lista de resultados
113
  etiqueta = {'Tweets': datos, 'Prediccion': predic['label'], 'Probabilidad': predic['score']}
114
  result.append(etiqueta)
115
  except:
116
  pass
117
+ # Crea un dataframe a partir de la lista de resultados
118
  df = pd.DataFrame(result)
119
+ # Si el dataframe está vacío, muestra un mensaje de que no se encontraron tweets sexistas dentro de la localidad
120
  if df.empty:
121
  muestra= st.text("No hay tweets Sexistas a analizar")
122
  tabla.append(muestra)
123
+
124
  else:
125
+ # ordena el dataframe por Predicción y Probabilidad en orden descendente
126
  df.sort_values(by=['Prediccion', 'Probabilidad'], ascending=[False, False], inplace=True)
127
  df['Prediccion'] = np.where(df['Prediccion'] == 'LABEL_1', 'Sexista', 'No Sexista')
128
  df['Probabilidad'] = df['Probabilidad'].apply(lambda x: round(x, 3))
129
  muestra = st.table(df.reset_index(drop=True).head(50).style.applymap(color_survived, subset=['Prediccion']))
 
 
 
130
  tabla.append(muestra)
131
  except Exception as e:
132
+ #Try except para detectar si la cuenta es existente
133
  muestra = st.text(f"La cuenta {usuario} no existe.")
134
  tabla.append(muestra)
135
  else:
136
+ #Condición que se solicita cuando no se llenaron los datos para la busqueda
137
  muestra= st.text("Ingrese los parametros correspondientes")
138
  tabla.append(muestra)
139
  return tabla
140
 
141
+ #Función para buscar por localidad
142
  def tweets_localidad(buscar_localidad):
143
+ tabla = [] # crea una lista vacía llamada tabla
144
  try:
145
+ #Crea un objeto Geolocalizador y busca la ubicación que se encuentra en el parámetro buscar_localidad
146
  geolocator = Nominatim(user_agent="nombre_del_usuario")
147
  location = geolocator.geocode(buscar_localidad)
148
+ radius = "15km" #establece el radio de búsqueda en 15km
149
+ # utiliza la API de Twitter para buscar tweets en español cerca de la ubicación encontrada
150
  tweets = api.search_tweets(q="",lang="es",geocode=f"{location.latitude},{location.longitude},{radius}", count = 100, tweet_mode="extended")
151
+ result = [] # crea una lista vacía llamada result
152
+ # itera a través de cada tweet en la lista de tweets encontrados
153
  for tweet in tweets:
154
+ # si el tweet comienza con 'RT' o si el tweet está vacío, continúa con el siguiente tweet
155
  if (tweet.full_text.startswith('RT')):
156
  continue
157
  elif not tweet.full_text.strip():
158
  continue
159
  else:
160
+ # Limpia los datos del tweet y realiza una predicción sobre si es sexista o no
161
  datos = limpieza_datos(tweet.full_text)
162
  prediction = pipeline_nlp(datos)
163
  for predic in prediction:
164
+ # Agrega la etiqueta de Tweets, Predicción y Probabilidad en una lista y la agrega a la lista de resultados
165
  etiqueta = {'Tweets': datos,'Prediccion': predic['label'], 'Probabilidad': predic['score']}
166
  result.append(etiqueta)
167
+ # Crea un dataframe a partir de la lista de resultados
168
  df = pd.DataFrame(result)
169
+ # Si el dataframe está vacío, muestra un mensaje de que no se encontraron tweets sexistas dentro de la localidad
170
  if df.empty:
171
  muestra=st.text("No se encontraron tweets sexistas dentro de la localidad")
172
  tabla.append(muestra)
173
  else:
174
  #tabla.append(muestra)
175
+ # ordena el dataframe por Predicción y Probabilidad en orden descendente
176
  df.sort_values(by=['Prediccion', 'Probabilidad'], ascending=[False, False], inplace=True)
177
+ # convierte la columna de Predicción en "Sexista" o "No Sexista" y redondea la columna de Probabilidad a 3 decimales
 
178
  df['Prediccion'] = np.where(df['Prediccion'] == 'LABEL_1', 'Sexista', 'No Sexista')
179
  df['Probabilidad'] = df['Probabilidad'].round(3)
180
  # Obtener los datos con probabilidad mayor a 0.50
 
189
  muestra_df = pd.concat([sexista_df, no_sexista_df], axis=0)
190
  col1, col2 = st.columns(2)
191
  with col1:
192
+ #lista de Tweets mostrados en pantalla
193
  muestra = st.table(muestra_df.reset_index(drop=True).head(6).style.applymap(color_survived, subset=['Prediccion']))
194
  with col2:
195
  resultado = df['Prediccion'].value_counts()
196
  def autopct_fun(abs_values):
197
  gen = iter(abs_values)
198
  return lambda pct: f"{pct:.1f}% ({next(gen)})"
199
+ #Gráfico
200
  colores=["#aae977","#EE3555"]
201
  fig, ax = plt.subplots()
202
  fig.set_size_inches(2,2)
 
234
  tabla = st.text("Solo Frase en español")
235
 
236
  return tabla
237
+
238
+ #Función para correr el formulario
239
  def run():
240
+ # Se inicia una sesión Streamlit
241
  with st.form("my_form"):
242
+ # Se solicita al usuario que ingrese la búsqueda que desea realizar
243
  search_words = st.text_input("Introduzca la frase, el usuario o localidad para analizar y pulse el check correspondiente")
244
+ # Se solicita al usuario que ingrese la cantidad de tweets que desea analizar (máximo 50)
245
  number_of_tweets = st.number_input('Introduzca número de tweets a analizar del usuario Máximo 50', 0,50,0)
246
  st.write("Escoja una Opción:")
247
+ # Se presenta al usuario las opciones de búsqueda (frase, usuario o localidad) mediante checkboxes
248
  termino=st.checkbox('Frase')
249
  usuario=st.checkbox('Usuario')
250
  localidad=st.checkbox('Localidad')
251
+ # Se agrega un botón de envío para que el usuario pueda iniciar la búsqueda
252
  submit_button = st.form_submit_button(label='Analizar')
253
+ # Se define una variable de error y se inicializa como falso
254
  error =False
255
+
256
+ # Si el usuario hace clic en el botón de envío, se comprueban los checkboxes y se establece un mensaje de error si es necesario
257
  if submit_button:
258
  # Condición para el caso de que esten dos check seleccionados
259
  if ( termino == False and usuario == False and localidad == False):
 
262
  elif ( termino == True and usuario == True and localidad == True):
263
  st.text('Error se han seleccionado varios check')
264
  error=True
265
+
266
+ # Si no se ha producido ningún error, se inicia la búsqueda según la opción seleccionada
267
  if (error == False):
268
  if (termino):
269
  analizar_frase(search_words)
 
271
  tweets_usuario(search_words,number_of_tweets)
272
  elif (localidad):
273
  tweets_localidad(search_words)
274
+
275
+ # Se ejecuta la función run
276
  run()