Repository navigation
Expand file tree
/
Copy pathvisualizaciones.py
More file actions
executable file
·327 lines (285 loc) · 12.2 KB
/
Copy pathvisualizaciones.py
File metadata and controls
executable file
·327 lines (285 loc) · 12.2 KB
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
#----------------------------------------------------------------------------
# Librerías
#----------------------------------------------------------------------------
from twython import Twython
from wordcloud import WordCloud, STOPWORDS
from pandas import DataFrame
import os
import re
import nltk
from nltk.corpus import stopwords
import sys
import json
import matplotlib as mpl
#Configurar para que no requiera X
mpl.use('Agg')
#----------------------------------------------------------------------------
# Variables Globales
#----------------------------------------------------------------------------
usingCommandLine = False
#----------------------------------------------------------------------------
# Funciones
#----------------------------------------------------------------------------
def generateWordCloud(words, width, height, bg_color, words_count, output_file_name):
'''
Creao un Wordcloud
La salida es en el directorio actual,
o la especificada en la línea de comandos
'''
stopwords = set(STOPWORDS)
text = ' '.join(words)
wc = WordCloud(width=width,
height=height,
background_color=bg_color,
max_words=words_count,
stopwords=stopwords,
random_state=1,
collocations=False).generate(text)
# Si se usa línea de comandos, se requiere todo el path de salida
if usingCommandLine is True:
wc.to_file(output_file_name)
# De lo contrario se pone en el directorio actual/images
else:
wc.to_file(os.path.join(os.getcwd(), output_file_name))
def cleanAndTokenizeText(list_TwitsText):
'''
Toma todo el texto, lo limpia de menciones,
hastags, emoticones, URL's, símbolos,
y palabras comunes no importantes para
el cometido, y retorna un list con todas
las palabras limpias.
'''
# patter para eliminar emoticons
emoji_pattern = re.compile("["
u"\U0001F600-\U0001F64F" # emoticons
u"\U0001F300-\U0001F5FF" # symbols & pictographs
u"\U0001F680-\U0001F6FF" # transport & map symbols
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
"]+", flags=re.UNICODE)
# cargo todo el texto en un solo string
clean_text = ' '.join(list_TwitsText)
# eliminar menciones
clean_text = re.sub(r'@([a-zA-Z0-9\\_\\.]+)', '', clean_text)
# eliminar urls
clean_text = re.sub(r'https:([a-zA-Z0-9\\_\\.\\/]+)', '', clean_text)
# eliminar hashtags
clean_text = re.sub('#([a-zA-Z0-9\\_\\.]+)', '', clean_text)
# eliminar números
clean_text = re.sub(r'[0-9]+', '', clean_text)
# eliminar emojis
clean_text = emoji_pattern.sub('', clean_text)
# eliminar otros símbolos
clean_text = re.sub(r'[^\w\ \_]', '', clean_text)
# tokenizar palabras nuevamente
terms_all = clean_text.split()
# filtro/exluyo palabras no requeridas
filtered_words = [
word
for word in terms_all
if word not in stopwords.words('english')
and
word not in stopwords.words('spanish')
and
len(word) > 3 # prevenir la, el, acá, y cosas por el estilo
]
# retorno las palabras
return filtered_words
def plotHist(data,bins,title,width,height,output_file_name):
'''
Genera un histograma de barras
y lo graba al archivo especificado
'''
mpl.pyplot.figure(figsize=(width/72,height/72))
mpl.pyplot.title(title)
cleanData=data[data!='und']
mpl.pyplot.hist(x=cleanData,bins=bins)
# Si se usa línea de comandos, se requiere todo el path de salida
if usingCommandLine is True:
mpl.pyplot.savefig(output_file_name)
# De lo contrario se pone en el directorio actual/images
else:
mpl.pyplot.savefig(os.path.join(os.getcwd(), output_file_name))
mpl.pyplot.clf()
return
#----------------------------------------------------------------------------
# Inicialización de Twitter
# Debes crear una aplicacion en https://apps.twitter.com para obtener
# el APP_KEY y el APP_SECRET
#----------------------------------------------------------------------------
# Authorizo Twython
APP_KEY = ''
APP_SECRET = ''
twythonInst = Twython(APP_KEY, APP_SECRET, oauth_version=2)
ACCESS_TOKEN = twythonInst.obtain_access_token()
twitterClient = Twython(APP_KEY, access_token=ACCESS_TOKEN)
#----------------------------------------------------------------------------
# Bajo últimos 100 tweets excluyendo los retweets
#------------------------------------------------------------------------------
# Para permitir usar en línea de comandos, y pasarle lo que se desea buscar
# si se paso los keywords via línea de commandos
try:
query = sys.argv[1]
usingCommandLine = True
except: # si no, cargar predeterminado
query = "#Uruguay"
# Buscar...
queryResult = twitterClient.search(q=query + ' -filter:retweets',
count=100)
# Si no se encontraron twits, salir
if len(queryResult['statuses']) == 0:
print("No twits found for the specified search keywords")
sys.exit(1)
#----------------------------------------------------------------------------
# Proceso los nombres de los archivos de salida en la línea de comandos
#----------------------------------------------------------------------------
if usingCommandLine == True:
try: # intento cargar los nombres
# nombre de archivo para screen names (usuarios mas activos)
mostactiveusers_file_name = sys.argv[2]
# nombre de archivo para palabras mas usadas
mostusedwords_file_name = sys.argv[3]
# nombre de archivo para nube de hashtags
hashtags_file_name = sys.argv[4]
# nombre de archivo para histograma de idiomas de tuits
langs_file_name = sys.argv[5]
except: # si alguno de los nombres no fue pasado error y salir
print("\n\nPlease specify desired output images filenames. Ex: \"tda_mentions\" \"tda_words\"")
sys.exit(1)
else: # en caso de no ser línea de commandos, asumir nombres
mostactiveusers_file_name = 'tda_mostactive.png'
mostusedwords_file_name = 'tda_words.png'
hashtags_file_name = 'tda_hashtags.png'
langs_file_name = 'tda_langs.png'
#----------------------------------------------------------------------------
# Descargar stopwords ...
#----------------------------------------------------------------------------
nltk.download("stopwords", quiet=True)
#----------------------------------------------------------------------------
# Conversion a DataFrame para mejor manipulacion
# Extracción de URL's, HashTags, screen_names, y demás info
#----------------------------------------------------------------------------
#creo dataframe vacío con las columnas a usar
df_tweets = DataFrame(columns=['ids','texts','screen_names','names','locations','descriptions','langs','hashtags','urls','images','link_to_tweet'])
#creao una lista vacía que contendrá los hashtags
lst_hashtags = []
#creo una lista vacía que contendrá las URL's
lst_urls = []
#creo una lista vacía que contendrá las imagenes/media y URL a tuit
lst_images = []
#creo una lista vacía que contendrá links directo to tuits
lst_links_to_tuits = []
#recorro todos los statuses
for status in queryResult['statuses']:
#lista hashtag vacía
hashtags=[]
#si hay alguna hashtag
if 'hashtags' in status['entities'] and len(status['entities']['hashtags']) > 0:
#recorro todos los hashtags y obtengo el texto en minúsculas
hashtags = [hashtag['text'].lower() for hashtag in status['entities']['hashtags']]
#lo agrego a la lista de hashtags global
lst_hashtags.extend(hashtags)
#lista urls vacía
urls=[]
#si hay alguna URL
if 'urls' in status['entities'] and len(status['entities']['urls']) > 0:
#recorro todas las urls, extraigo la url expandida y la agrego a urls
urls = [url['expanded_url'] for url in status['entities']['urls']]
#agrego las urls encontradas a la lista
lst_urls.extend(urls)
#genero link to tuit
link_to_tweet = 'https://twitter.com/statuses/'+status['id_str']
#agrego link to tuit a la lista
lst_links_to_tuits.append(link_to_tweet)
#lista urls imágenes vacía
images=[]
#si hay alguna URL
if 'media' in status['entities'] and len(status['entities']['media']) > 0:
#recorro todas las urls, extraigo la url expandida y la agrego a urls
images = [image['media_url'] for image in status['entities']['media']]
#agrego las urls encontradas a la lista y el link al su tuit
lst_images.append({"images":images,"url":link_to_tweet})
#agrego nueva fila de datos al dataframe
df_tweets = df_tweets.append({
'ids': status['id'],
'texts': status['text'],
'screen_names': status['user']['screen_name'],
'names': status['user']['name'],
'locations': status['user']['location'],
'descriptions': status['user']['description'],
'langs': status['lang'],
'users_time_zones': status['user']['time_zone'],
'hashtags':hashtags,
'urls':urls,
'images':images,
'link_to_tweet':link_to_tweet
},ignore_index=True)
#----------------------------------------------------------------------------
# Extracción de Screen Names
#----------------------------------------------------------------------------
# Hago una nube de palabras de los usuarios que mas tuitearon sobre el tema
# y con un máximo de 60 screen names
generateWordCloud(words=df_tweets['screen_names'],
width=800,
height=400,
bg_color='black',
words_count=60,
output_file_name=mostactiveusers_file_name)
#----------------------------------------------------------------------------
# Extracción de Palabras Mas Usadas
#----------------------------------------------------------------------------
# Veo qué palabras son las más usadas en los tueets que mencionan los keywords,
# sacando los emoticones, las menciones, las urls, y los hastags
tweets_words = cleanAndTokenizeText(df_tweets['texts'])
# Hago una nube de palabras con las palabras mas usadas
# y con un máximo de 60 palabras mostradas
generateWordCloud(words=tweets_words,
width=800,
height=400,
bg_color='black',
words_count=60,
output_file_name=mostusedwords_file_name)
#----------------------------------------------------------------------------
# Extracción de HashTags mas usados
#----------------------------------------------------------------------------
# Hago una nube de palabras con los hashtags mas usados
# y con un máximo de 60 palabras mostradas
generateWordCloud(words=lst_hashtags,
width=800,
height=400,
bg_color='black',
words_count=60,
output_file_name=hashtags_file_name)
#----------------------------------------------------------------------------
# Histograma de idiomas
#----------------------------------------------------------------------------
plotHist(data=df_tweets['langs'],
bins=6,
title='Most Relevant Languages',
width=800,
height=400,
output_file_name=langs_file_name)
# Si estamos en línea de comandos, devolver los caminos a los archivos generados
if usingCommandLine == True:
#creo objeto con estructura para JSON
results = {
'images':
{
'users':mostactiveusers_file_name,
'words': mostusedwords_file_name,
'hashtags':hashtags_file_name,
'tlangs': langs_file_name,
},
'media':
{
'tweet_images':lst_images,
'shared_urls':lst_urls
}
}
#convierto objeto a string json y lo retorno
print(json.dumps(results))
else:
print(os.path.join(os.getcwd(), mostactiveusers_file_name))
print(os.path.join(os.getcwd(), mostusedwords_file_name))
print(os.path.join(os.getcwd(), hashtags_file_name))
print(os.path.join(os.getcwd(), langs_file_name))
print("Done!")