File size: 10,600 Bytes
a86ebfe
074b087
4f600ec
 
123a2a5
64547bc
4c1a7b2
eb03325
4913bb4
edb53bb
074b087
336e489
4c1a7b2
a76f382
4913bb4
a86ebfe
336e489
a76f382
 
 
336e489
a86ebfe
 
 
 
 
 
 
1b4e97e
bfaf0da
4913bb4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0e521b1
e5f8353
 
 
 
 
 
 
bc97bc5
074b087
 
 
3fc23ca
e7fc6e7
fc2c6f0
 
 
 
 
9e0c8f4
1b4e97e
9e0c8f4
1b4e97e
9e0c8f4
3b9d4b9
 
 
074b087
1b4e97e
 
 
074b087
1b4e97e
9e0c8f4
1b4e97e
074b087
1b4e97e
457d41e
7c434c5
bfaf0da
0eaa842
bfaf0da
d0e7d06
 
bfaf0da
 
d0e7d06
 
 
 
 
4913bb4
 
 
 
bfaf0da
4913bb4
 
 
 
 
 
 
 
 
d0e7d06
 
cfaf805
7386027
2ba6811
70da8b4
 
 
3943bfc
7386027
d8e3643
7386027
 
f9ed481
7386027
bfaf0da
7386027
0e521b1
7c434c5
3e92edb
1bf00e3
dc1887d
 
 
ec5e9ed
9ffd42a
dad8f09
bb0de7f
485e4eb
d5291cb
4f31ce9
dad8f09
 
bfaf0da
6de011c
dad8f09
6de011c
fe0b968
a7ff4ae
6de011c
7386027
 
6de011c
46ac277
69864c1
 
46ac277
645e710
bdb23ce
a0c7133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bdb23ce
f95ab68
bb0de7f
46ac277
7386027
 
dad8f09
7386027
bb0de7f
7c434c5
bb0de7f
33f003a
eb4e7e0
7386027
 
4913bb4
89d7f96
 
 
 
 
 
 
33f003a
dfcadc4
 
89d7f96
b9decf4
90917fe
021bcd0
366279c
 
a882dd0
 
 
 
 
 
 
 
f043bf1
a882dd0
 
 
 
 
 
 
 
f043bf1
a882dd0
 
366279c
a882dd0
366279c
a882dd0
366279c
021bcd0
074b087
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import tweepy as tw
import streamlit as st
import pandas as pd
import regex as re
import numpy as np
import pysentimiento
import geopy
import matplotlib.pyplot as plt
import langdetect


from pysentimiento.preprocessing import preprocess_tweet
from geopy.geocoders import Nominatim
from transformers import pipeline
from langdetect import detect


model_checkpoint = "hackathon-pln-es/twitter_sexismo-finetuned-robertuito-exist2021" 
pipeline_nlp = pipeline("text-classification", model=model_checkpoint)

    
consumer_key = "BjipwQslVG4vBdy4qK318KnoA"
consumer_secret = "3fzL70v9faklrPgvTi3zbofw9rwk92fgGdtAslFkFYt8kGmqBJ"
access_token = "1217853705086799872-Y5zEChpTeKccuLY3XJRXDPPZhNrlba"
access_token_secret = "pqQ5aFSJxzJ2xnI6yhVtNjQO36FOu8DBOH6DtUrPAU54J"
auth = tw.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tw.API(auth, wait_on_rate_limit=True)
   
def limpieza_datos(tweet):
    # Eliminar emojis
    tweet = re.sub(r'[\U0001F600-\U0001F64F]', '', tweet)
    tweet = re.sub(r'[\U0001F300-\U0001F5FF]', '', tweet)
    tweet = re.sub(r'[\U0001F680-\U0001F6FF]', '', tweet)
    tweet = re.sub(r'[\U0001F1E0-\U0001F1FF]', '', tweet)
    # Eliminar arrobas
    tweet = re.sub(r'@\w+', '', tweet)
    # Eliminar URL
    tweet = re.sub(r'http\S+', '', tweet)
    # Eliminar hashtags
    tweet = re.sub(r'#\w+', '', tweet)
    # Eliminar caracteres especiales
    #tweet = re.sub(r'[^a-zA-Z0-9 \n\.]', '', tweet)
    tweet = re.sub(r'[^a-zA-Z0-9 \n\áéíóúÁÉÍÓÚñÑ.]', '', tweet)
    return tweet

def highlight_survived(s):
    return ['background-color: red']*len(s) if (s.Sexista == 1) else ['background-color: green']*len(s)

def color_survived(val):
    color = 'red' if val=='Sexista' else 'white'
    return f'background-color: {color}'


st.set_page_config(layout="wide")
st.markdown('<style>body{background-color: Blue;}</style>',unsafe_allow_html=True)

#st.markdown('<style>body{background-color: Blue;}</style>',unsafe_allow_html=True)
#colT1,colT2 = st.columns([2,8])
st.markdown(""" <style> .fondo {
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");
background-size: 180%;} 
</style> """, unsafe_allow_html=True)


st.markdown(""" <style> .font {
font-size:40px ; font-family: 'Cooper Black'; color: #301E67;} 
</style> """, unsafe_allow_html=True)

#st.markdown('<p class="font"; style="text-align: center;>Análisis de comentarios sexistas en linea</p>', unsafe_allow_html=True)
st.markdown('<p class="font" style="text-align: center;">Análisis de comentarios sexistas en linea</p>', unsafe_allow_html=True)

    
st.markdown(""" <style> .font1 {
font-size:28px ; font-family: 'Times New Roman'; color: #8d33ff;} 
</style> """, unsafe_allow_html=True)

st.markdown(""" <style> .font2 {
font-size:16px ; font-family: 'Times New Roman'; color: #5B8FB9;} 
</style> """, unsafe_allow_html=True)

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 sexistas. Los resultados se almacenan en un dataframe para su posterior visualización y análisis. El objetivo del proyecto es identificar y proporcionar información sobre el discurso sexista en línea para combatir la discriminación y el acoso hacia las mujeres y otros grupos marginados, y así informar políticas y prácticas que promuevan la igualdad de género y la inclusión.</p>',unsafe_allow_html=True)


def tweets_usuario(usuario, cant_de_tweets):
  tabla = []
  if(cant_de_tweets > 0 and usuario != "" ):
      try:
          # Buscar la información del perfil de usuario
          user = api.get_user(screen_name=usuario)
          tweets = api.user_timeline(screen_name = usuario,tweet_mode="extended", count= cant_de_tweets)
          result = []
          for tweet in tweets:
              if (tweet.full_text.startswith('RT')):
                  continue
              else:
                  text = tweet.full_text
                  try:
                      language = detect(text)
                      if language == 'es':
                          datos=limpieza_datos(text)
                          if datos == "":
                              continue
                          else:
                              prediction = pipeline_nlp(datos)
                              for predic in prediction:
                                etiqueta = {'Tweets': datos, 'Prediccion': predic['label'], 'Probabilidad': predic['score']}
                                result.append(etiqueta)
                  except:
                      pass   
          df = pd.DataFrame(result)
          if df.empty:
              muestra= st.text("No hay tweets Sexistas a analizar")
              tabla.append(muestra)
          else:
              df.sort_values(by=['Prediccion', 'Probabilidad'], ascending=[False, False], inplace=True)
              df['Prediccion'] = np.where(df['Prediccion'] == 'LABEL_1', 'Sexista', 'No Sexista')
              df['Probabilidad'] = df['Probabilidad'].apply(lambda x: round(x, 3))
              muestra = st.table(df.reset_index(drop=True).head(30).style.applymap(color_survived, subset=['Prediccion']), max_rows=9)
              tabla.append(muestra)
      except Exception as e:
          muestra = st.text(f"La cuenta {search_words} no existe.") 
          tabla.append(muestra) 
  else:
      muestra= st.text("Ingrese los parametros correspondientes")
      tabla.append(muestra)      
  return tabla


def tweets_localidad(buscar_localidad):
    tabla = []
    try:
        geolocator = Nominatim(user_agent="nombre_del_usuario")
        location = geolocator.geocode(buscar_localidad)
        radius = "15km"
        tweets = api.search_tweets(q="",lang="es",geocode=f"{location.latitude},{location.longitude},{radius}", count = 1000, tweet_mode="extended")
        result = []
        for tweet in tweets:
            if (tweet.full_text.startswith('RT')):
                continue
            elif not tweet.full_text.strip():
                continue
            else:
                datos = limpieza_datos(tweet.full_text)
                prediction = pipeline_nlp(datos)
                for predic in prediction:
                    etiqueta = {'Tweets': datos,'Prediccion': predic['label'], 'Probabilidad': predic['score']}
                    result.append(etiqueta)
        df = pd.DataFrame(result)
        if df.empty:
            muestra=st.text("No se encontraron tweets sexistas dentro de la localidad")
            tabla.append(muestra)
        else:
            #tabla.append(muestra)
            df.sort_values(by=['Prediccion', 'Probabilidad'], ascending=[False, False], inplace=True)
            #df.sort_values(by='Prediccion', ascending=False, inplace=True)
            df['Prediccion'] = np.where(df['Prediccion'] == 'LABEL_1', 'Sexista', 'No Sexista')
            df['Probabilidad'] = df['Probabilidad'].round(3)
            
            col1, col2 = st.columns(2)
            with col1:
                muestra = st.table(df.reset_index(drop=True).head(5).style.applymap(color_survived, subset=['Prediccion']))
            with col2:
                resultado = df['Prediccion'].value_counts()
                colores=["#EE3555","#aae977"]
                fig, ax = plt.subplots()
                fig.set_size_inches(2, 2)
                plt.pie(resultado,labels=resultado.index,autopct='%1.1f%%',colors=colores,  textprops={'fontsize': 4})
                ax.set_title("Porcentajes por Categorias", fontsize=5, fontweight="bold")
                plt.rcParams.update({'font.size':4, 'font.weight':'bold'})
                ax.legend()
                # Muestra el gráfico
                plt.show()
                st.set_option('deprecation.showPyplotGlobalUse', False)
                #st.pyplot()

            
        
    except AttributeError as e:
        muestra=st.text("No existe ninguna localidad con ese nombre") 
        tabla.append(muestra)
                 
    return tabla 
    
   
def analizar_frase(frase):
    language = detect(frase)
    if frase == "":
        tabla = st.text("Ingrese una frase")
        #st.text("Ingrese una frase")
    elif language == 'es':
        predictions = pipeline_nlp(frase)
        # convierte las predicciones en una lista de diccionarios
        data = [{'Texto': frase, 'Prediccion': prediction['label'], 'Probabilidad': prediction['score']} for prediction in predictions]
        # crea un DataFrame a partir de la lista de diccionarios
        df = pd.DataFrame(data)
        df['Prediccion'] = np.where( df['Prediccion'] == 'LABEL_1', 'Sexista', 'No Sexista')
        # muestra el DataFrame
        tabla = st.table(df.reset_index(drop=True).head(1).style.applymap(color_survived, subset=['Prediccion']))
    else:
        tabla = st.text("Solo Frase en español")
        
    return tabla

def run():
    #col1, col2 = st.columns(2)
    with st.form("my_form"):
        search_words = st.text_input("Introduzca la frase, el usuario o localidad para analizar y pulse el check correspondiente")
        number_of_tweets = st.number_input('Introduzca número de tweets a analizar del usuario Máximo 50', 0,50,0)
        st.write("Escoja una Opción")
        termino=st.checkbox('Frase')
        usuario=st.checkbox('Usuario')
        localidad=st.checkbox('Localidad')
        submit_button = st.form_submit_button(label='Analizar')
        error =False
           
        if submit_button:
            # Condición para el caso de que esten dos check seleccionados
            if ( termino == False and usuario == False and localidad == False):
                st.text('Error no se ha seleccionado ningun check')
                error=True
            elif ( termino == True and usuario == True and localidad == True):
                st.text('Error se han seleccionado varios check')
                error=True
                   
        if (error == False):
          if (termino):
              analizar_frase(search_words)
          elif (usuario):
              tweets_usuario(search_words,number_of_tweets)
          elif (localidad):
              tweets_localidad(search_words)
   
run()