En este post aprenderás cómo extraer tweets de un trending topic de Twitter utilizando Python, guardarlos en un archivo de texto y luego obtener cuáles son las cuentas más influyentes y las palabras más repetidas del topic. Estos son los pasos que tienes que realizar:
La mejor forma de extraer datos de Twitter es mediante su API. Esta tiene algunas limitaciones. Por ejemplo, se puede hacer hasta 300 requerimientos por aplicación cada 15 minutos; 500 mil tweets por proyecto, por mes; entre otros límites que podrás visualizar cuando tengas listo tu dashboard de desarrollador.
Para usar la API necesitas crear una cuenta de desarrollador y autenticarte. Para ello, realiza los siguientes pasos:
credentials.py
y guárdalas ahí porque Twitter no te las volverá a mostrar, solo te permitirá regenerarlas.credentials.py
.Y listo, ¡ya tienes todo lo que necesitas para empezar a extraer tweets y almacenarlos!
Si por alguna razón tu solicitud fue rechazada, al final del post comparto el repositorio de lo trabajado y ahí te dejaré 3 archivos de texto con miles de tweets para que, con fines educativos, puedas practicar todo lo que veremos.
Ahora que ya tienes las keys y token, hay muchas maneras en las que te puedes conectar con Twitter. Te recomiendo hacerlo con una librería de Python llamada Tweepy, puesto que esta viene con varios métodos para aprovechar al máximo todo lo que permite hacer la API de Twitter.
En este post nos vamos a centrar en un par de métodos específicos, pero en la documentación de tweepy encontrarás detalladamente todas las cosas que puedes llegar a hacer, como obtener todos los tweets de un usuario, recibir tweets en tiempo real, ver detalladamente toda la información que guarda cada tweet, etc. Así que te invito a darle una mirada y mejorar o modificar todo lo que te enseñe a continuación.
Empecemos instalando la dependencia. Por buenas prácticas, te recomiendo hacerlo en un entorno virtual. Si aún no sabes cómo crear uno, revisa esta clase del curso de Python Intermedio.
Ahora que ya tienes el entorno creado y activado, puedes instalar Tweepy con pip, ejecutando en la consola:
pip install tweepy
Recapitulando, dentro de la carpeta de tu proyecto tienes un archivo llamado credentials.py
que contiene lo siguiente:
API_KEY = 'YOUR_API_KEY'
API_SECRET_KEY = 'YOUR_API_SECRET_KEY'
ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN'
ACCESS_TOKEN_SECRET = 'YOUR_ACCESS_TOKEN_SECRET'
Ahora vamos a crear un archivo nuevo en el que ejecutaremos la lógica del programa, yo le llamaré give_me_tweets.py
. En este primero hay que importar las credenciales y tweepy:
import credentials
import tweepy
Ahora debes hacer el proceso de autenticación e ingresar a la API, para ello tweepy nos soluciona todo ejecutando estas líneas:
auth = tweepy.OAuthHandler(credentials.API_KEY, credentials.API_SECRET_KEY)
auth.set_access_token(credentials.ACCESS_TOKEN, credentials.ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)
¡Eso es todo! Ahora ya estás conectado a la API de Twitter y tienes un mundo de posibilidades por delante. ¿Quieres hacer una prueba rápida? Ejecuta este código para imprimir tu timeline en la consola:
public_tweets = api.home_timeline()
for tweet in public_tweets:
print(f'{tweet.user.screen_name}:\n{tweet.text}\n{"*"*60}')
A partir de aquí vas a trabajar con tu propio topic, puede ser un hashtag (podrías escoger algún trending topic de tu país y luego analizar qué está pasando) o un término. En mi caso trabajaré con “One Piece”.
Necesitamos realizar un programa que almacene en un archivo de texto toda la cantidad de tweets que la API nos permita, esto es aproximadamente 3000 tweets cada 15 minutos, así que usemos ese límite. Para hacer esto usaremos un ciclo while y un contador que haga que el ciclo se detenga al llegar a 3000.
Para buscar tweets hay que usar el método api.search()
. Si quieres profundizar sobre todos sus parámetros, acá te dejo la documentación. Pero en este caso nos vamos a enfocar en 4 parámetros: q: el topic que escogiste; lang: lenguaje; tweet_mode: extensión del tweet; max_id: tweets más antiguos que el especificado.
Traduciendo todo esto a código, quedaría de esta manera:
id = None
count = 0while count <= 3000:
tweets = api.search(q='one piece', lang='es', tweet_mode='extended', max_id=id)
id = tweet.id
En cada clico se consultarán aproximadamente 15 tweets. Lo coloqué en lenguaje en español para que más adelante sea sencillo limpiar los datos. El tweet mode extended permite que se obtengan los tweets con 280 caracteres. Y por último es muy importante crear la variable id = None
y al final del ciclo asignarle el id del último ciclo para que en cada ciclo se consulten solo los tweets más antiguos que los ya consultados en el último ciclo. Caso contrario, siempre se estarían obteniendo los mismos 15 tweets.
Ahora solo queda almacenar los archivos, para ello hay que crear un ciclo for justo después de que se haga la consulta. Acá hay que abrir un archivo con permisos para añadir más elementos y añadir en cada línea un nuevo tweet. Por último, como buena práctica, cerrar el archivo e imprimir en qué iteración está del ciclo para que cuando ejecutes el programa puedas ver cuántos tweets vas.
for tweet in tweets:
f = open('./onepiece.txt', 'a', encoding='utf-8')
f.write(tweet.full_text + '\n')
f.close
Si quieres que no se te guarden los retweets, podrías añadir un condicional al principio del ciclo for que haga que se salte esa iteración si el tweet inicia con “RT”. Añadiendo eso, tu programa debería quedar de esta manera:
id = None
count = 0while count <= 3000:
tweets = api.search(q='one piece', lang='es', tweet_mode='extended', max_id=id)
for tweet in tweets:
if tweet.full_text.startswith('RT'):
count += 1continue
f = open('./onepiece.txt', 'a', encoding='utf-8')
f.write(tweet.full_text + '\n')
f.close
count += 1
id = tweet.id
print(count)
Ahora solo debes ejecutar el programa en la consola y se te creará el archivo .txt y se irán agregando ahí todos los tweets hasta llegar a los 3000 o hasta que se detenga automáticamente por exceder el rate limit. Si pasa esto último, dentro de 15 minutos podrás seguir añadiendo más tweets.
¡Ya lograste obtener miles de tweets y almacenarlos, has progresado mucho! Pero no lo dejemos aquí, finalicemos esto haciendo un análisis de toda la información que ahora tenemos. Acompáñame 👇
Esta parte la realizaremos en un nuevo archivo que llamaré analyzer.py
. Para empezar necesitamos excluir algunas palabras como los artículos porque siempre aparecerán como las palabras más usadas y no es lo que buscamos. Para ello te dejo aquí una lista de palabras que a mi criterio debería excluir:
exclude_words = ['el', 'la', 'los', 'las', 'un', 'una', 'unos', 'unas', 'al', 'del', 'lo', 'le', 'y', 'e', 'o', 'u', 'de', 'a', 'en', 'que', 'es', 'por', 'para', 'con', 'se', 'su', 'les', 'me', 'q', 'te', 'pero', 'mi', 'ya', 'cuando', 'como', 'estoy', 'voy', 'porque', 'he', 'son', 'solo', 'tengo', 'muy']
Crea un diccionario vacío, llamado top_words
, en el que luego añadiremos el top de palabras. Ahora deberás acceder con permisos de lectura al archivo en el que tienes almacenados los tweets, para a continuación, guardar cada palabra del archivo como key del diccionario y que su valor sea las veces que se repite en total entre todos los tweets.
Podrías hacerlo con un ciclo for que recorra cada línea del archivo, y en cada una elimine espacios, ponga todas las palabras en minúsculas, las divida una por una y las guarde en una lista llamada words
.
top_words = {}
tweets_topic = open('./onepiece.txt', encoding='utf-8')
for line in tweets_topic:
words = line.strip().lower().split()
Por último, para almacenar cada una de las palabras, utiliza otro ciclo for que itere por cada ciclo de la lista words
. En este incluye la condicional para que no se incluyan las palabras excluidas.
Para añadir cada palabra del ciclo al diccionario top_words
, colócalas como key del diccionario. Para asignar su valor, usa el método get
, el cual en su primer parámetro evalúa si ya existe esa key, en caso de que sí exista, deja su mismo valor anterior, pero en caso de que no, en su segundo parámetro le asigna un valor. Y luego, añade un + 1
para indicar que se encontró una vez más la palabra. El código final quedaría algo así:
top_words = {}
tweets_topic = open('./onepiece.txt', encoding='utf-8')
for line in tweets_topic:
words = line.strip().lower().split()
for word in words:
if word notin exclude_words:
top_words[word] = top_words.get(word, 0) + 1
Si te sientes algo confundido, prueba imprimir en la consola words
y top_words
, para que veas qué contienen cada una. También prueba quitar el + 1
al asignar los valores al diccionario, para que notes como sin esa suma, no se contarán nuevas palabras.
Ahora vamos a ordenar el diccionario de mayor a menor para que sea más sencillo obtener las cuentas y palabras más usadas. Esto se puede lograr con el método sorted
. Pasándole como primer parámetro el diccionario. El segundo parámetro indica con base a qué será ordenado, así que le indicaremos que lo haga por valor. Y el tercer parámetro es para indicar que ordene de mayor a menor porque por defecto ordena de menor a mayor.
most_used_words = sorted(top_words, key=top_words.get, reverse=True)
Teniendo el diccionario ordenado, ya está todo listo para imprimir los 10 usuarios más mencionados en este topic. Cuando se menciona un usuario, la palabra inicia por “@”, así que usaremos el método startwith
para encontrarlos. Por lo tanto, todo lo que necesitamos es un ciclo que imprima los 10 primeros valores, seguidos de su key en most_used_words
, que cumplan con la condición de iniciar con “@”.
count_u = 0for word in most_used_words:
if count_u < 10and word.startswith('@'):
print(top_words[word], word)
count_u += 1
print('*'*40) # esto es para separar visualmente la información
Ya obtuvimos los 10 usuarios más relevantes. Para finalizar, de la misma manera que con los usuarios, se pueden imprimir las palabras más usadas, solo que esta vez eliminando la condicional de empezar con “@” y aumentando a 20 el total de palabras a imprimir.
count = 0for word in most_used_words:
if count < 20:
print(top_words[word], word)
count += 1
¡Eso es todo! Solo ejecuta analyzer.py
en la consola y podrás visualizar tus resultados. Déjame en los comentarios de este post qué es lo que obtuviste y tu análisis de lo que estás viendo.
En mi caso encontré algunas cosas interesantes como que las personas mencionan mucho a Naruto cuando hablan de One Piece. La palabra “yo” es la #8 más usada y “Luffy” (el personaje principal) está en la posición #9. La palabra “no” es 3.33x veces más usada que la palabra “si”. Y que la cuenta más mencionada es @daitedice, que irónicamente tiene una foto de perfil de Naruto.
Como lo prometido es deuda, acá te dejo el repositorio en el que agregué todos los archivos que usé y, en caso de que te hayan rechazado la solicitud a la API de twitter, dejé 3 archivos con miles de tweets en cada uno para que practiques. Uno es onepiece.txt
, que es con el que yo trabajé. El otro es aborto.txt
, en donde recopilé un trending topic de mi país, Ecuador, en donde se aprobó una ley sobre el tema. Y finalmente, añadí uno sobre platzi.txt
. Recuerda que su uso es con fines educativos.
Si no entendiste algunas cosas del código de este post, te recomiendo ir a tomar el Curso de Python Intermedio. Este curso te dará todas las bases que necesitas para entender todo lo que hicimos y mucho más. Toma el curso y pronto estaré trayendo tutoriales más avanzados para que pongas en práctica todo lo nuevo que descubras. ¡Y nunca pares de aprender! 💚
Me gustaría que dentro de Platzi hubiera una sección, aparte de los cursos, donde se grabaran estos tipos de tutoriales. Le harían una fuerte y necesaria competencia a los tutoriales que hay en Youtube.
Sí, tienen ese tipo de cosas, pero solo hasta ahí. YouTube gana terreno en la diversidad de contenido que tienen. Tutoriales como estos podrían añadirle gran valor a la suscripción de Platzi.
seria genial tambien poder guardar este tipo de posts, tener una función de agregar a una lista como se hace con los cursos.
por ahora bookmark la página.
Competencia de los mejores toturiales
¡Vaya pero que joyita!
Yo analice BTC y estos fueron mis resultados
53 @mstrswtch
27 @bitso
21 @nayibbukele
19 @ladymarketok
17 @rodrigofaez
17 @javier30670747
16 @wallstwolverine
15 @michael_saylor
13 @guaje7rsg
13 @alejandro_btc
629 btc
582 no
512 #btc
282 #bitcoin
259 $btc
236 si
175 más
137 #criptomonedas
126 precio
108 bitcoin
105 hay
96 está
93 #crypto
90 esta
88 ahora
86 $eth
86 #trading
84 comprar
84 yo
83 #eth
Wow, que interesantes resultados! Tanto cuentas como palabras. Muchas gracias por compartirlo 💚
Me gustó! lo voy a poner en práctica y te aviso.!
¡Genial! Estaré atento a sus resultados 😄
Joyita almacenada para proceder a estudio
Excelente tengo varias ideas para usar esto.
Gracias a este post estoy aprendiendo a usar esta librería, e hice un ejemplo como el que Anthony hizo, con el hashtag #Colombia.
Es muy interesante el análisis de lo que sucede en Twitter gracias a esto.
Sii, está muy interesante analizar ese trending por la situación actual. Te recomiendo que importes el módulo time y en tu ciclo while (cambiando los 3000 por True) para obtener tweets, uses time.sleep (podría ser de 5 a 10 segundos). Con eso podrías dejar un buen rato corriendo el programa para que extraiga la mayor cantidad de tweets sin que te dé error por exceder los límites de la API.
Adicional, está genial que hayas graficado los resultados 😄 Si nos compartes tu código para graficar estaría genial 💚
Muchas gracias Anthony :3
¿Cómo tendría que usar el
sleep
ahí?Claro que sí! El código que usé es el siguiente:
# Dictionary Info. ''' Mi diccionario se llama "mentioned". Entonces extraigo sus keys y valores.'''keys = list(mentioned.keys()) values = list(mentioned.values()) # Parte gráfica, usando pyplot plt.rcdefaults() fig, ax = plt.subplots() ax.barh(keys, values, align='center', label = values) ax.set_yticks(keys) ax.set_yticklabels(keys) ax.invert_yaxis() # labels read top-to-bottom ax.set_xlabel('Frequency') ax.set_title('Trending #Colombia') for i, v in enumerate(values): ax.text(v + 3, i + .25, str(v), color='blue', fontweight='normal') plt.show()
Muy interesante, justo estoy por empezar este curso. GRACIAS.!
Increíble aporte amigo, lo practicaré en este momento. Gracias.
Excelente tutorial lo pondré en práctica. Espero que Twitter me apruebe el acceso a la API. Excelente Aporte. Gracias.
Genial! Excelente aporte a la comunidad.
Muchas gracias por este gran aporte.
En mi caso, tuve que escribir “r” antes de la ruta completa del archivo, si no, no me escribe los tweets en el archivo. Así:
tweets_topic = open(r"C:\Users\Jared\Documents\Ciencia de Datos Platzi\Proyecto_Extraer_Tweets\exportar_vino.txt", encoding=‘utf-8’)
Excelente, es el segundo tutorial tuyo que sigo, funciona muy bien.
Muchas gracias.
Anthony que buen post!
Justo quería extraer de Twitter el precio del dólar de varias cuentas para promediarlo y me había vuelto un ocho.
Gracias por compartir esto.
Buen aporte!! sin duda que tiene mucha utilidad.
Muchas gracias Anthony, me lo agrego a favoritos.
Hey que buen tutorial 😄
Sabes como es el procedimiento para obtener datos desde la API de LinkendIn? Justo estoy trabajando con eso y tengo muchas dudas :'v
QUE BUEN TUTORIAL POR DIOS 😄
Siii, tienes razón.
Ahora lo que estoy haciendo es web scrapping, porque no me quedó de otra XD
Que tutorial tan genial , espero puedas seguir compartiendo proyectos de este tipo en python. Muchas felicidades!
Muchas gracias 😃
Y sí, intentaré hacer tutoriales de cosas nuevas que aprenda todos los meses 💚 de hecho este mismo mes tengo pensado escribir uno sobre análisis de sentimientos usando este tutorial como base
Esta muy bueno el tutorial, la explicación, la documentación, todo. Le veo mucha utilidad en especial para los que manejan data de este tipo.
Yo estoy en nivel básico en Python así que todavía me falta algo de recorrido para poder sacarle provecho. Pero para los que ya estén avanzados aprovechen !!!
Muchas Gracias Anthony Ismael.
Gracias por tu comentario 😃
Y si ya tomaste el Curso Básico de Python y ya practicaste lo aprendido, solo toma el Curso Intermedio de Python y entenderás el 100% del tutorial para que también lo pongas en práctica y nos compartas tus resultados 😄
Está buenísimo esto :3
Esto puede ser muy útil para marketing, para investigación. Son datos muy interesantes.
Wow, me encanto el potencial del lenguaje! Como puedo hacer para que se coloque algun simbolo o espacio entre tweet y tweet? No se cuando empieza y termina cada uno.
Muy bueno el post! Sin dudas dan ganas de aprender Python
Hola 😃
En esta parte:
f = open('./onepiece.txt', 'a', encoding='utf-8') f.write(tweet.full_text + '\n') f.close
Podrías añadir esto para poner un separador de asteriscos:
f = open('./onepiece.txt', 'a', encoding='utf-8') f.write(tweet.full_text + '\n' + '*'*40 + '\n') f.close
El resultado que tendrás será algo así:
Gracias por esa recomendacion y por tu tiempo! :gre
Amigo eres un crack, muchas gracias por el aporte.
esta genial, muchas gracias
¿Hay manera de guardar este blog en algún lado o sección de mi perfil? es decir, si quiero verlo dentro de x meses, ¿cuál sería la manera más fácil de hacerlo? (omitiendo la opción de guardar el link en un bloc de notas o algo así :v)
Existe la opción desde la app móvil 🤔 pero es medio raro el proceso, cuando abro un blog de Platzi desde el navegador del cel, aparece para ponerle una estrellita y luego en la parte de Favoritos > Blogpost aparece. También creo que se puede guardar si los abres desde la app.
La verdad lo que yo hago cuando quiero guardar blogpost, los pongo en Notion 😅
Entiendo, gracias por tu respuesta Anthony 😃
Hola Anthony. Pregunta off-topic: ¿Cómo le haces para grabar gifs de tu computador para elaborar mini-tutoriales? Tengo MacOs
😮
Ayuda 😦 Me Aparece este error:
because running scripts is disabled on this system. For more information, see about_Execution_Policies at
https:/go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:3
Hola, siguiendo el tutoríal me presenta el siguiente error:
AttributeError: ‘API’ object has no attribute ‘search’
Como lo puedo solucionar?
Hola, en vez de ese search puedes utilizar:
tweets = api.search_tweets(q='one piece', lang='en', tweet_mode='extended', max_id=id)```
Hola, Anthony Ismael @anthony_manotoa
Excelente tu tutorial!!!
Revisé y en la última versión de Tweepy, .search fue reemplazado por .search_tweets
Por otra parte, en la documentación dice que API.search_tweets
"Returns a collection of relevant Tweets matching a specified query.“
Es decir
"Devuelve una colección de Tweets relevantes que coinciden con una consulta especificada.”
Lo que no me queda claro es si son TODOS los Tweets que coinciden o solo una fracción de todos ellos que la API considera “relevante”.
¿Me podrías ayudar?
Thanks!
Hola Anthony gragiac
Hola Anthony gracias por el tutotorial, tengo el siguente problema al ejecutar la comprovacion
"public_tweets = api.home_timeline()
for tweet in public_tweets:
print(f’{tweet.user.screen_name}:\n{tweet.text}\n{"*"*60}’)"
Resulta:
Exception has occurred: Forbidden
403 Forbidden
453 - You currently have Essential access which includes access to Twitter API v2 endpoints only. If you need access to this endpoint, you’ll need to apply for Elevated access via the Developer Portal. You can learn more here: https://developer.twitter.com/en/docs/twitter-api/getting-started/about-twitter-api#v2-access-leve
Me sale este error: TweepError: [{‘code’: 32, ‘message’: ‘Could not authenticate you.’}]
Al tratar de realizar la Configuración de autenticación de usuario tengo que completar lo siguiente:
Y no se como completar, ayuda porfa
Super bueno
MUY BUENP COMPA
OMG! Impactada! Definitivamente tomaré este tutorial :3
Gracias Anthony, ideal para analizar el marketing político.
Me parecio increible la idea y quise probarlo 😄, pero parece que esta linea devuelve None no se porque y a partir de eso no imprime nada:
auth = tweepy.OAuthHandler(credentials.API_KEY, credentials.API_SECRET_KEY)
Me fije bien de copiar bien las claves y tokens 😦
Podrías probar escribir directamente las tus keys como parámetros en la línea que nos compartes. También revisar que no hayas regenerado las claves por error en Twitter 🤔
Wow!
Me da un error con la linea
id = tweet.id
Ya lo resolví, pero me está trayendo el mismo Twitt 180 veces
Hola, Nestor 😄
El error podría estar en la identación 🤔 o en el parámetro
max_id=id
. Podrías compartirme tu código para ayudarte 💚