Para acceder a los sistemas de Twitter necesitamos obtener una autorización, identificándonos con nuestro usuario en la red. Este paso es inevitable, ya que sin una autorización Twitter no responderá nuestras consultas. Por suerte, el trámite para obtener acceso es inmediato, y como resultado obtendremos una serie de códigos de identificación, conocidos en su conjunto como API keys.
El primer paso es, si no lo hemos hecho aún, crear un usuario de Twitter en https://twitter.com/signup. Luego seguimos los pasos de éste instructivo https://towardsdatascience.com/access-data-from-twitter-api-using-r-and-or-python-b8ac342d3efe. Nota: Twitter nos preguntará cómo se llama la “app” para la cual estamos solicitand acceso. No vamos a crear ninguna app, pero aún así tenemos que elegir un nombre; usemos “RTWEET” (aunque podría ser cualquier otro). Al completar los pasos estaremos en poder de cuatro códigos: Consumer Key, Consumer Secret, Access Token y Access Token Secret. Tomemos nota de ellos.
rtweet
provee un conjunto de funciones que nos facilitan interactuar con Twitter. Si no lo tenemos instalado, lo conseguimos vía:
install.packages("rtweet")
Y lo activamos junto al resto de los paquetes que vamos a usar.
library(rtweet)
library(tidyverse)
A continuación, le pasamos a rtweet
los datos de autorización que conseguimos antes para crear un “token” (en la jerga de Twitter, es una especie de comprobante de que estamos autorizados a acceder a los datos)
# El nombre que le asgnamos a la app en el formulario de autorización
appname <- "RTWEET"
## consumer key (en el ejemplo no es una clave real, usar la verdadera)
consumer_key <- "la_secuencia_de_caracteres_de_nuestra_consumer_key"
## consumer secret (en el ejemplo no es un clave real, usar la verdadera)
consumer_secret <- "la_secuencia_de_caracteres_de_nuestra_consumer_secret"
## consumer key (en el ejemplo no es una clave real, usar la verdadera)
access_token <- "la_secuencia_de_caracteres_de_nuestro_access_token"
## consumer secret (en el ejemplo no es un clave real, usar la verdadera)
access_secret <- "la_secuencia_de_caracteres_de_nuestro_access_secret"
twitter_token <- create_token(
app = appname,
consumer_key = consumer_key,
consumer_secret = consumer_secret,
access_token = access_token,
access_secret = access_secret)
A continuación se abrirá una ventana en nuestro navegador solicitando autorizar el acceso vía R -lo aceptamos, por supuesto.
Ahora si, estamos listos para realizar consultas en el archivo de Twitter. La función search_tweets()
permite obtener tweets que cumplan los requisitos que fijemos. Por ejemplo, para buscar tweets que contienen el término “inflacion”, usamos:
tweets <- search_tweets(q = "inflacion", n = 3000)
El parámetro n = 3000 es para limitar la búsqueda a los primeros 3000 tweets hallados.
También puede hacerse una búsqueda por múltiples términos. Por ejemplo, buscando “ciudad+universitaria” hace que twitter devuelva resultads donde las palabras aparecen juntas y en ese orden; como alternativa, al optar por “ciudad universitaria” se obtienen tweets donde aparezcan esas palabras en cualquier parte del texto, sin importar su orden o si aparecen contiguas.
El resultado es un dataframe de 3000 observaciones -el número máximo que habíamos solicitado- y 88 columnas. rtweet
incluye users_data()
, una función que muestra detalles de los usuarios que han producido los tweets que capturamos:
users_data(tweets) %>% head()
También podemos explorar los resultados en base a las 88 variables disponibles. Revisemos los nombres:
names(tweets)
## [1] "user_id" "status_id"
## [3] "created_at" "screen_name"
## [5] "text" "source"
## [7] "display_text_width" "reply_to_status_id"
## [9] "reply_to_user_id" "reply_to_screen_name"
## [11] "is_quote" "is_retweet"
## [13] "favorite_count" "retweet_count"
## [15] "quote_count" "reply_count"
## [17] "hashtags" "symbols"
## [19] "urls_url" "urls_t.co"
## [21] "urls_expanded_url" "media_url"
## [23] "media_t.co" "media_expanded_url"
## [25] "media_type" "ext_media_url"
## [27] "ext_media_t.co" "ext_media_expanded_url"
## [29] "ext_media_type" "mentions_user_id"
## [31] "mentions_screen_name" "lang"
## [33] "quoted_status_id" "quoted_text"
## [35] "quoted_created_at" "quoted_source"
## [37] "quoted_favorite_count" "quoted_retweet_count"
## [39] "quoted_user_id" "quoted_screen_name"
## [41] "quoted_name" "quoted_followers_count"
## [43] "quoted_friends_count" "quoted_statuses_count"
## [45] "quoted_location" "quoted_description"
## [47] "quoted_verified" "retweet_status_id"
## [49] "retweet_text" "retweet_created_at"
## [51] "retweet_source" "retweet_favorite_count"
## [53] "retweet_retweet_count" "retweet_user_id"
## [55] "retweet_screen_name" "retweet_name"
## [57] "retweet_followers_count" "retweet_friends_count"
## [59] "retweet_statuses_count" "retweet_location"
## [61] "retweet_description" "retweet_verified"
## [63] "place_url" "place_name"
## [65] "place_full_name" "place_type"
## [67] "country" "country_code"
## [69] "geo_coords" "coords_coords"
## [71] "bbox_coords" "status_url"
## [73] "name" "location"
## [75] "description" "url"
## [77] "protected" "followers_count"
## [79] "friends_count" "listed_count"
## [81] "statuses_count" "favourites_count"
## [83] "account_created_at" "verified"
## [85] "profile_url" "profile_expanded_url"
## [87] "account_lang" "profile_banner_url"
## [89] "profile_background_url" "profile_image_url"
Allí hay de todo para explorar. Por ejemplo,
Según la cantidad de seguidores:
options(scipen = 20)
ggplot(tweets) +
geom_histogram(aes(x = followers_count))
El gráfico muestra una distribución de “power law”, típica en los rankings de popularidad. Hay una enorme masa de usuarios con popularidad mínima (apenas un puñado de seguidores) y un número muy pequeño de usuarios que alcanza una cantidad deseguidores cientos o miles de veces superior a la de la mayoría.
Obtenemos un top 5 de los usuarios más populares (con más seguidores), su procedencia, y el contenido del tweet:
tweets %>%
top_n(5, followers_count) %>%
arrange(desc(followers_count)) %>%
select(screen_name, followers_count, location, text)
En base a la cantidad de retweets que recibieron. Nos quedamos sólo con los tweets originales, descartando los que son retweets en si mismos (“is_retweet == TRUE”), y revisamos la distribución de sus retweets:
ggplot(filter(tweets, !is_retweet))+
geom_histogram(aes(x = retweet_count))
Otra ditribución power law. Identifiquemos el tweet original más que sumó más retweets:
tweets %>%
filter(!is_retweet) %>%
filter(retweet_count == max(retweet_count)) %>%
select(screen_name, retweet_count, followers_count, location, text)
Nota: Si no estamos interesados en capturar retweets, podemos evitarlos al momento de consultar la base de Twitter, as’i tweets <- search_tweets(q = "inflacion", n = 500, include_rts = FALSE)
rtweet()
provee una funció que hace facil mostrar la evolución temporal de nuestros tweets: ts_plot()
. Podemos ver la frecuencia de tweets por segundo, hora, día, semana, mes o año eligiendo el parámetro correspondiente (“secondss”, “minutess”, “hours”, “days”, “weeks”, “months”, o “years”)
ts_plot(tweets, "minutes")
tweets %>%
ggplot() +
geom_bar(aes(location)) +
coord_flip() +
labs(title = "Procedencia de los usuarios",
x = "cantidad",
y = "ubicación")
Dado que el campo “location” refleja el texto que cada usuario eligió para describir su ubicación (no se trata de las coordenadas de origen del tweet) las variabilidad es grande. Algunas escriben su país, otros su ciudad, otras su barrio… y hay quienes eligen opciones poéticas cómo “algún lugar del mundo”. En todo caso, la abundancia de opciones resulta en un gráfico muy difícil de leer.
Probamos extraer el top 10 de lugares más frecuentes, eliminando los tweets de usuarios sin datos en su atributo “location”.
tweets %>%
filter(location != "", !is.na(location)) %>%
count(location) %>%
top_n(10, n) %>%
ggplot() +
geom_col(aes(x = reorder(location, n), y = n)) +
coord_flip() +
labs(title = "Procedencia de los usuarios",
x = "ubicación",
y = "cantidad")
Finalmente, hacemos un mapa que uestre el origen de los mensajes. Algunos de los tweets tienen coordenadas geográficas (en el campo “geo_coords”), pero la mayoría no tiene datos de ubicación más allá de la procedencia declarada por el usuario. Más adelante vamos a trabajar con tweets georeferenciados, los que tienen coordenadas; pero por ahora nos conformamos con la procedencia de los usuarios, que podemos convertir en latitud y longitud consultando el servicio de geolocalización de Google. Para poder usarlo necesitamos obtener una API key (una clave de acceso al servicio), siguiendo las instrucciones que figuran aquí: https://blog.ensalza.com/api-google-maps/
Una vez que tenemos nuestra API key, la cargamos:
# Activamos el paquete ggmap
library(ggmap)
# Cargamos nuestra api key
api_key <- "codigo_de_la_api__cortar_y_pegar_aqui"
register_google(key = api_key)
Ahora podemos geolocalizar (obtener coordenadas geográficas) de los lugares de procedencia de los usuarios en nuestros tweets, usando la función geocode()
procedencia_tweets <- tweets %>%
sample_n(100) %>% # tomamos una muestra al azar de 100 filas
filter(!is.na(location), location != "") %>%
pull(location) %>%
geocode() %>%
group_by(lon, lat) %>%
summarise(cantidad = n())
head(procedencia_tweets)
Y ahora si, al mapa. No necesitamos descargar un mapa base; podemos usar un dataset con las fronteras mundiales que viene includo con ggplot.
ggplot(procedencia_tweets) +
borders("world") +
geom_point(aes(x = lon, y = lat, size = cantidad), alpha = .4, color = "orange") +
labs(title = "Procedencia de los tweets capturados")
Como alternativa a consultar el archivo “histórico” de Twitter, es posible conectar a su API de streaming, que entrega tweets en tiempo real al instante en que se producen. La función stream_tweets()
permite iniciar una conección y capturar tweets hasta concluya el tiempo dispuesto por el parámetro “timeout”, expresado en segundos.
Por ejemplo, para “escuchar” el stream de Twitter por un minuto (60 segundos), y capturar mensajes que incluyan la frase último momento:
captura_streaming <- stream_tweets(q = "último+momento", timeout = 60)
Verificamos el resultado (sólo los campos de usuario y texto del tweet):
captura_streaming[4:5]
Cuando queremos monitorear un evento de actualidad, por ejemplo capturando tweets que mencionen una palabra o hashtag de interés, resulta necesario mantener las escucha activa durante varias horas o días. La solución para este caso es usar la función stream_tweets2()
, que permite iniciar un proceso de escucha de tiempo arbitrario. Dado que no se sabe que puede fallar en un proceso que dura varios días, la función se encarga de guardar los resultados en un archivo local a medida que se obtienen, y reiniciar la conexión a Twitter en forma automática si se interrumpe por algún motivo (como un corte momentáneo de acceso a internet).
La usamos así:
terminos_de_busqueda <- "donald+trump OR vladimir+putin"
#una semana: 60 segundos * 60 * 24 * 7
tiempo <- 60 * 60 * 24 * 7
# El archivo donde guardar los resultados en disco (tendrá formato json, así que lo usamos en el nombre de archivo)
archivo <- "busqueda_tweets_DT_VP.json"
stream_tweets(q = terminos_de_busqueda,
timeout = tiempo,
file_name = archivo,
parse = FALSE)
Una vez que el período de captura termina, podemos leer el archivo generado.
# en el paso anterior definimos que el nombre de archivo es "busqueda_tweets_DT_VP.json"
tweets <- parse_stream("busqueda_tweets_DT_VP.json")
Y con eso concluye el proceso. Ya estamos listos para analizar el contenido.
¡Generar un archivo propio de tweets no es tan difícil!