Matt-CB/TwitterAccountAnalyzer
0
1import os2import csv3import openai 4import random5from dotenv import load_dotenv6from nltk.corpus import stopwords7from nltk.tokenize import word_tokenize8from nltk import pos_tag9from collections import Counter10import nltk11nltk.download('punkt')12from transformers import pipeline13from mtranslate import translate14import pandas as pd15import streamlit as st16from PIL import Image17import time18 19 20 #Para actualizar las librerias de requirements.txt en caso de error, escribir esto en consola: pip install --upgrade -r requirements.txt21load_dotenv()22st.sidebar.title("Configuración")23OPENAI_API_KEY = st.sidebar.text_input("API KEY:")24st.write("Ingresa los datos ")25IDIOMAS = ['Alemán', 'Español', 'Francés', 'Inglés', 'Italiano']26idioma = st.sidebar.selectbox("Idioma:", IDIOMAS)27 28 29 30 31class AnalizadorTwitter:32 def __init__(self):33 self.TWEETS_DIR = 'tweets'34 nltk.download('averaged_perceptron_tagger')35 nltk.download('stopwords')36 37 def generar_tweets(self, usuario:str, num_tweets:int=10, max_tokens:int=50, aleatoriedad:float=1):38 openai.api_key = OPENAI_API_KEY39 os.makedirs(self.TWEETS_DIR, exist_ok=True)40 archivo_csv = os.path.join(self.TWEETS_DIR, f"{usuario}_tweets.csv")41 archivo_existente = os.path.exists(archivo_csv)42 43 temas = ["Deportes", "Entretenimiento", "Política", "Tecnología", "Moda y belleza", "Viajes", "Negocios y finanzas", "Redes sociales e internet", "Comida y restaurantes", "Música", "Arte y cultura", "Ciencia y naturaleza", "Educación", "Videojuegos", "Humor y memes", "Tecnología e innovación", "Hogar y diseño de interiores", "Relaciones y citas", "Espiritualidad y religión", "Mascotas y animales"]44 emociones = ["Felicidad", "Tristeza", "Emoción", "Miedo", "Amor", "Asombro", "Enojo", "Sorpresa", "Diversión", "Paz"]45 46 tema = random.choice(temas)47 print(idioma, tema)48 49 with open(archivo_csv, 'a', newline='', encoding='utf-8') as archivo:50 writer = csv.writer(archivo)51 52 if not archivo_existente:53 writer.writerow(['user', 'tweet'])54 55 for i in range(num_tweets):56 emocion = random.choice(emociones)57 prompt = f"Generar un tweet corto #{i+1} centrado en el tema de {tema}. El tweet debe expresar una emoción de {emocion} con una intensidad alta y que se noten las palabras expresivas hacia ese sentimiento, pero sin dejar de ser realista. Debe ser redactado si o si todo en {idioma}, que sea nivel nativo de {idioma}. Evita incluir emojis en el contenido del tweet. Asegúrate de que el tweet esté completamente en {idioma}, y que las emociones y los sentimientos reflejen la intensidad solicitada antes de proporcionar la respuesta."58 59 response = openai.Completion.create(60 engine='text-davinci-003',61 prompt=prompt,62 max_tokens=max_tokens,63 temperature=aleatoriedad,64 n=1,65 stop=None,66 )67 68 tweet = response.choices[0].text.strip()69 70 writer.writerow([usuario, tweet])71 72 def identificar_tema_principal(self, dataframe, idioma):73 tweets = dataframe['tweet'].tolist()74 # Seleccionar stopwords según el idioma75 if idioma == "Alemán":76 stop_words = set(stopwords.words('german'))77 elif idioma == "Español":78 stop_words = set(stopwords.words('spanish'))79 elif idioma == "Francés":80 stop_words = set(stopwords.words('french'))81 elif idioma == "Inglés":82 stop_words = set(stopwords.words('english'))83 elif idioma == "Italiano":84 stop_words = set(stopwords.words('italian'))85 else:86 raise ValueError("Idioma no soportado")87 88 # Tokenización de palabras y eliminación de stopwords89 palabras = [word for tweet in tweets for word in word_tokenize(tweet.lower()) if word.isalpha() and word not in stop_words]90 91 # Etiquetado de partes del discurso92 tagged_words = pos_tag(palabras)93 94 # Contar la frecuencia de cada palabra95 frecuencia_palabras = Counter(tagged_words)96 97 # Ordenar las palabras por frecuencia98 palabras_ordenadas = sorted(frecuencia_palabras.items(), key=lambda x: x[1], reverse=True)99 100 # Obtener el tema principal como la palabra más frecuente con etiqueta de sustantivo101 tema_principal = None102 for palabra, frecuencia in palabras_ordenadas:103 if 'NN' in palabra[1]: # Verificar si la palabra tiene etiqueta de sustantivo104 tema_principal = palabra[0]105 break106 107 return tema_principal108 109 def traducir_columna(self, df, idioma):110 df_traducido = df.copy()111 if idioma == 'inglés':112 return df_traducido113 else:114 df_traducido['tweet_ingles'] = df_traducido['tweet'].apply(lambda x: translate(x, 'en'))115 return df_traducido116 117 def agregar_columna_emociones(self, df, idioma):118 clasificador = pipeline("text-classification", model="thoriqfy/indobert-emotion-classification")119 emociones_detectadas = []120 if idioma != 'inglés':121 data = self.traducir_columna(df, idioma)122 for texto in data['tweet_ingles']:123 outputs = clasificador(texto)124 emocion = outputs[0]['label']125 emociones_detectadas.append(emocion)126 else:127 data = df128 for texto in data['tweet']:129 outputs = clasificador(texto)130 emocion = outputs[0]['label']131 emociones_detectadas.append(emocion)132 data['emocion_detectada'] = emociones_detectadas133 134 #menciona todas las columnas de data135 136 137 return data138 139 140 @staticmethod141 def obtener_sentimiento(score):142 if score < 0.4:143 return 'Negativo'144 elif score < 0.6:145 return 'Neutro'146 else:147 return 'Positivo'148 149 150 def identificar_sentimiento(self, dataframe, idioma):151 modelo = ''152 if idioma.lower() == "alemán".lower():153 modelo = "oliverguhr/german-sentiment-bert"154 elif idioma.lower() == "español".lower():155 modelo = "dccuchile/bert-base-spanish-wwm-uncased"156 elif idioma.lower() == "francés".lower():157 modelo = "nlptown/bert-base-multilingual-uncased-sentiment"158 elif idioma.lower() == "inglés".lower():159 modelo = "bert-base-uncased"160 elif idioma.lower() == "italiano".lower():161 modelo = "Musixmatch/umberto-commoncrawl-cased-v1"162 163 clasificador_sentimiento = pipeline("sentiment-analysis", model=modelo)164 sentimientos = []165 for texto in dataframe['tweet']:166 resultado = clasificador_sentimiento(texto)167 etiqueta = resultado[0]['label']168 score = resultado[0]['score']169 sentimiento = self.obtener_sentimiento(score)170 sentimientos.append(sentimiento)171 dataframe['sentimiento'] = sentimientos172 return dataframe173 174 175 176 177 178def main():179 180 181 column1, column2 = st.columns([1.5, 1])182 column1.markdown("<h1 style='text-align: left; color: white;'>Análisis de <span style='color: #1DA1F2;'>Twitter</span></h1>", unsafe_allow_html=True)183 column2.image("images/Logo_of_Twitter.png", width=100)184 185 186 usuario = st.sidebar.text_input("Nombre de usuario:", "usuario_ejemplo")187 st.sidebar.markdown('<p style="font-size:12px;color:#1DA1F2;">No dejar espacios en el nombre y apellido</p>', unsafe_allow_html=True)188 st.sidebar.title('Configuración de parametros para el generador de tweets')189 num_tweets = st.sidebar.number_input("Número de tweets:", 1, 100, 10)190 st.sidebar.markdown('<p style="font-size:12px;color:#1DA1F2;">Colocar como min 5 tweets</p>', unsafe_allow_html=True) #191 max_tokens = st.sidebar.number_input("Máximo de tokens:", 1, 100, 50)192 aleatoriedad = st.sidebar.slider("Aleatoriedad:", 0.0, 1.0, 1.0)193 #idioma = st.sidebar.selectbox("Idioma:", IDIOMAS)194 tema = None195 sentimientos = ["Todos", "Positivo", "Neutro", "Negativo"]196 sentimiento = st.sidebar.selectbox("Sentimientos:", sentimientos)197 analizador = AnalizadorTwitter()198 if st.sidebar.button("Analizar"):199 with st.spinner("Generando tweets..."):200 analizador.generar_tweets(usuario, num_tweets, max_tokens, aleatoriedad)201 with st.spinner("Identificando tema principal..."):202 archivo_csv = os.path.join(analizador.TWEETS_DIR, f"{usuario}_tweets.csv")203 df = pd.read_csv(archivo_csv)204 tema = analizador.identificar_tema_principal(df, idioma)205 with st.spinner("Traduciendo tweets (si es necesario)..."):206 df_traducido = analizador.traducir_columna(df, idioma)207 with st.spinner("Detectando sentimientos..."):208 df_sentimiento = analizador.identificar_sentimiento(df, idioma)209 with st.spinner("Detectando emociones..."):210 df_emociones = analizador.agregar_columna_emociones(df_traducido, idioma)211 st.write("Cuenta: ", usuario)212 st.write("Tema principal: ", tema)213 st.write("Tabla de sentimientos:")214 st.dataframe(df_sentimiento)215 st.write("Tabla de emociones:")216 st.dataframe(df_emociones)217 st.markdown("# Tweets:")218 for i in df_emociones.index:219 row_emocion = df_emociones.loc[i]220 row_sentimiento = df_sentimiento.loc[i]221 if sentimiento == "Todos" or row_sentimiento["sentimiento"] == sentimiento:222 st.write(usuario, ':', row_emocion["tweet"])223 st.write("Emoción detectada: ", row_emocion["emocion_detectada"], f"- Sentimiento detectado: {row_sentimiento['sentimiento']}")224 225 226if __name__ == "__main__":227 main()228 229 