Twitter no es solo una fuente ampliada de noticias, es con diferencia una de las mejores muestras de los pensamientos del mundo. Con más de 330 millones de usuarios activos, es una de las principales plataformas donde a la gente le gusta compartir sus pensamientos. Los datos de Twitter se pueden utilizar para una variedad de propósitos como investigación, información sobre los consumidores, información demográfica, y muchos más.
Por lo tanto, el objetivo principal de este tutorial es enseñarle cómo obtener una muestra de datos de Twitter relevantes para su proyecto o negocio.
Antes de continuar, asegúrese de tener a mano todas estas variables:
- Consumer Key
- Consumer Secret
- Access Token
- Access Token Secret
Si desea saber cómo adquirir los detalles mencionados anteriormente, vaya a leer esa publicación de blog escrita por mi colega Dattatray Upase.
Now let’s do some coding!
Definición de las variables de entrada
Primero, tiene que definir algunas de las variables globales que necesitaría para el programa:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import sys start_date = sys.argv[1] #"2018-01-09" end_date = sys.argv[2] #"2018-01-10" consumerKey="Ingrese_Aquí_Su_Consumer_Key" consumerSecret="Ingrese_Aquí_Su_Consumer_Secret" accessToken="Ingrese_Aquí_Su_Access_Token" accessTokenSecret="Ingrese_Aquí_Su_Access_Token_Secret" keyword= sys.argv[3] #"tcs" lang="en" #vea lo que ofrece twitter para el filtrado de idiomas data={} |
Estoy importando ‘sys’ para obtener argumentos de la línea de comandos, porque podría querer cambiar las palabras clave, la fecha de inicio o la fecha de finalización. Para el idioma elegí el inglés, pero es posible que desee verificar qué otros idiomas son compatibles. Los resultados se almacenarán en ‘data’ al final.
Como resultado, un uso típico del script sería así:
python script.py start_date end_date keyword
Acceso a la API de Twitter
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import oauth2 req_count = 0 def oauth_req(url, http_method="GET", post_body=b"", http_headers=None): global req_count,consumerKey,consumerSecret,accessToken,accessTokenSecret req_count += 1 consumer = oauth2.Consumer(key=consumerKey, secret=consumerSecret) token = oauth2.Token(key=accessToken, secret=accessTokenSecret) client = oauth2.Client(consumer, token) resp, content = client.request( url, method=http_method, body=post_body , headers=http_headers ) return content |
La variable req_count es el número de veces que he usado la API en la ejecución de mi programa. Me encuentro con el siguiente error con el código proporcionado:
TypeError: Unicode-objects must be encoded before hashing
Para evitar esto, estoy cambiando post_body=”” a post_body=b”” y eso soluciona el problema.
Uso y referencia de la API de Twitter
Es hora de configurar la URL de la API para obtener los datos de Twitter. Estoy usando el parámetro min_faves. Aquí está la explicación de la URL y algunos trucos de optimización:
‘min_faves’ se utiliza para establecer el número mínimo de favoritos que debe tener un tweet en los datos. Es una función muy útil pero no se menciona en la documentación de la API de Twitter.
‘q’ representa la consulta o las palabras clave que desea ingresar. Aquí es importante asegurarse de proporcionar la menor cantidad de palabras clave posible. Por ejemplo, imaginemos que quiero tweets sobre Facebook y Google. Si proporciono ambos como palabras clave, por ejemplo, FACEBOOK y GOOGLE, solo me devolverá un máximo de 100 tweets, ya que esa es una restricción. Pero si ejecuto la consulta dos veces, una con Facebook y otra con Google, puedo obtener un total de 200 tweets. En resumen, es mejor usar una palabra clave por consulta.
‘lang’ representa el idioma de los tweets filtrados. Como quiero obtener tweets en inglés, lo configuro en ‘en’.
‘since’ es la fecha de inicio del período en el que desea buscar tweets. Esta fecha de inicio debe ser de los últimos 7 días. Esta es otra función que no está documentada en la documentación de la API de Twitter.
‘until’ representa la fecha de finalización de su período deseado. Lógicamente, también debería ser de los últimos 7 días. Tampoco está documentado en la documentación de la API de Twitter.
‘result_type’ representa el tipo de tweets que desea. Tiene 3 valores:
‘recent’ proporciona los tweets más recientes, es decir, los tweets al final del período seleccionado.
‘popular’ proporciona los tweets más populares y, por lo tanto, se pierde muchos tweets. Siempre obtendría los tweets con los favoritos y retweets principales. El min_faves la función no sería de ninguna utilidad aquí.
‘mixed’ proporciona una mezcla de tweets recientes y populares.
‘count’ representa el número máximo de tweets en el resultado. El valor predeterminado está establecido en 15 y el máximo es 100.
Con el result_type mixto y el uso de min_faves, podemos obtener el máximo de tweets ejecutando la consulta varias veces.
|
1 2 3 |
def get_tweets(min_faves): global keyword, start_date, end_date, lang return oauth_req( 'https://api.twitter.com/1.1/search/tweets.json?' + '&q=' + keyword + '&lang=' + lang + '%20since%3A' + start_date + '%20until%3A' + end_date + '%20min_faves%3A' + str(min_faves) +'&result_type=mixed&count=100') |
Para obtener más funciones documentadas, también puede consultar la documentación de la API de Twitter.
Guardar/Autoguardar los datos de tweets recuperados
Como siguiente paso, debe definir un método de autoguardado/guardado que tenga un parámetro ‘saveOverride’. Este paso simplemente es necesario para eliminar la restricción de tiempo de autoguardado y guardar el archivo. Para hacer esto, creo un t_last para guardar la hora de inicio del programa. Luego accedo al mismo en el programa y verifico si han pasado 5 minutos desde el t_last (última hora de guardado). Si han pasado más de 5 minutos, marco el ‘saveStatus’ como True.
A continuación, verifico ‘saveOverride’, lo que simplemente significa que necesito dar instrucciones a mi programa de que, pase lo que pase, el archivo debe guardarse ahora. Para esto, configuro el saveStatus como True.
Luego, si ‘saveStatus’ es True, el script cambiará el t_last a la hora actual. Después de eso, el código crea un objeto de diccionario e imprime “Autoguardado en [time]” para que sepa que los datos se están autoguardando.
A continuación, verifico si el archivo de salida ya existe. Si es así, combino los datos y los datos de un archivo ya guardado. Después de combinarlos, los escribo en el mismo archivo. Si no existe, creo un archivo nuevo y luego escribo los datos en ese archivo.
|
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 |
import os import json import time import datetime t_last = time.time() def autosave(saveOverride = False): global t_last saveStatus = (time.time() > t_last + 300) if(saveOverride == True):en" saveStatus = True if(saveStatus): t_last=time.time() tmp = {} print("Autoguardado en " + str(datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S"))) fnamea = keyword + "-st-" + start_date + "-ed-"+ end_date + '.json' if os.path.exists(fnamea) == True: with open(fnamea,'r+') as f: tmp = json.load(f) for i in data.keys(): tmp[i] = data[i] with open(fnamea,'w+') as f: json.dump(tmp,f) |
Como resultado, he programado casi toda la funcionalidad que quería.
Optimizando aún más
Finalmente, es hora de hacer uso de estas funciones. Estoy escribiendo un bucle while(1), lo que significa while(True). Esto básicamente hace que la instrucción se ejecute indefinidamente hasta que se llame a alguna declaración ‘break’ o se produzca alguna excepción.
Primero, recopilo los datos de los tweets en el diccionario ‘d’ usando json.loads que convierte los datos en un formato de diccionario. Luego, ejecuto un try-catch/except en el bloque de código que extrae los estados de los datos. Uso try-catch porque a veces la API de Twitter no devuelve datos sino un JSON que menciona el error. No quiero que mi programa se detenga en tales casos. Además, quiero que recupere en qué número de solicitud está ocurriendo eso y que guarde mis datos de Twitter usando el comando de autoguardado. Twitter nos permite realizar 180 solicitudes cada 15 minutos. Eso es como 12 solicitudes por minuto o una solicitud cada cinco segundos. Solo para estar seguro, agrego un comando sleep para que mi programa se duerma durante 5 segundos después de ejecutar una iteración.
Después de eso, el código mostrará la cantidad de tweets que el script ha recopilado hasta el momento.
Finalmente, es hora del principal truco de optimización. Estuve probando este script durante casi una semana y obtuve la siguiente cantidad de tweets para cada valor de min_faves . Puedo obtener un máximo de 100 tweets por solicitud y quiero obtener tantos como sea posible. Actualmente, no hay muchos tweets con valores más altos de min_faves pero queremos tener en cuenta los momentos en que, tal vez, la empresa o la palabra clave son tendencia. El valor máximo de min_faves puede ser 999999.
| Valor de min_faves | Número de tweets |
| 100,000 | 1 |
| 90,000 | 1 |
| 80,000 | 1 |
| 70,000 | 2 |
| 60,000 | 3 |
| 50,000 | 6 |
| 40,000 | 6 |
| 30,000 | 12 |
| 25,000 | 12 |
Por lo tanto, estoy usando una lógica que obtendría tweets desde un valor de min_faves de 60000 y luego lo disminuye en 10000 cada vez hasta llegar a 10000. Pero si, por ejemplo, la palabra clave es tendencia y obtengo 100 tweets cuando estoy trabajando con el valor de min_faves en 30000, va a aumentar el min_faves a 35000 y luego obtener los resultados de nuevo. Así que ahora la nueva lógica es 5000 en lugar de 10000. Sin embargo, si el cambio disminuye a menos de 1000, le pido que lo ignore y continúe restando 1000.
Estoy especificando un intervalo fijo de 1000 que min_faves debería disminuir si min_faves es menor o igual a 10000.
Al final del programa, el programa le informará que el trabajo ha terminado mostrando ‘End’.
|
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 |
min_faves=60000 change=10000 #reducción alta en min_faves para extraer datos interval = 500 #reducción normal en min_faves para extraer datos while(1): d = json.loads(get_tweets(min_faves)) try: for i in d['statuses']: data[i['id']] = i c = len(d['statuses']) except Exception as e: print("Error en la solicitud: " + str(req_count)) autosave(True) print("En la solicitud: " + str(req_count) + " Total de Tweets Recopilados: " + str(len(data)) + " con Min Faves: " + str(min_faves) ) if c==100 and min_faves>10000: if (change>1000): change /= 2 min_faves += change else: min_faves -= change elif min_faves>10000: min_faves -= change else: min_faves -= interval if(min_faves < 0): fnamea = keyword + '.json' autosave(True) break autosave() time.sleep(5) print("End") |
Puedes encontrar el código completo en GitHub.
Eso es todo. En el próximo tutorial de datos de Twitter, te enseñaré cómo recuperar tweets en tiempo real utilizando la herramienta de big data ‘Flume’. ¡Mantente atento!
Comentarios
Aún no hay comentarios. Sea el primero.