Geolocalizando tweets con Python. Tutorial 1

Abstract: Primer tutorial para capturar tweets y añadirlos a una base de datos Postgres para su posterior visualización en un mapa.
Hace unos meses vi unos artículos interesantes sobre la utilización de la plataforma Twitter para realizar estudios de análisis espacial o visualización de datos. Aunque es probable que ya los conozcáis, os dejo unos enlaces por aquí. Mapa de tweets en África, Lenguas en Londres

La idea me pareció tan interesante que investigué un poco en la creación de estos mapas. Una de las conclusiones que saqué es que no es nada fácil hacer estudios de ese nivel. Se necesitan gran cantidad de datos (tweets, en este caso) que no son nada fáciles de conseguir. Así como software para “moverlos”. Y cómo no, los conocimientos, ideas o metas a las que se pretenden llegar, ya los pone cada uno.
En mi caso, tan sólo quería experimentar un poco en la accesibilidad de la fuente de datos, es decir, recuperar unos cuantos tweets para ver qué pasa, y más adelante realizar algún tipo de análisis. Por ello me puse a buscar en la red, y vi que no era nada fácil. Por eso, tras realizar mis investigaciones, decidí hacer un pequeño tutorial sobre cómo lo hice. He decidido dividirlo en varias partes. En primer lugar explicar un poco cómo recuperé los tweets, utilizando Python y PostgreSQL, después, dotar la base de datos de geometría para poder visualizarlos con cualquier SIG que lo permita, y por último, intentaré hacer alguna visualización con los datos obtenidos.

Crear el script python que capture tweets:

Para capturar los tweets he crado un pequeño script en Python que recoge todos los datos generados según un query. De momento está un poco verde, aún le quedan cosas por mejorar e implementar para hacerlo más fácil, pero funcionar funciona. El script se ha creado con la librería tweepy, y su funcionamiento no es más que generar una serie de pticiones y guardar los tweets devueltos que tengan coordenadas. Algunas de las funcionalidades son las siguientes:
Hacer la conexión a la api de búsqueda de Twitter mediante tweepy. De momento lo he configurado para recoger todos los tweets en lengua española, pues es lo que necesitaba para la base del estudio, pero obviamente se pueden pasar otros parámetros como las palabras clave, o buscar todos los tweets por coordenadas. Esto lo dejaré para otros estudios. También queda pendiente el desarrollo del script para hacer esto más fácil, o su limpieza.
peticion=  tweepy.api.search(q="*", rpp=100, lang='es')
En esta parte es en la que itero por los tweets devueltos (100) para sacar sus propiedades. Así, le estoy diciendo que para la petición devuelta en el objeto “petición” (que consta de 100 tweets, de ahí el rpp=100) me devuelva las propiedades que le he seleccionado. Estas propiedades son las necesarias para luego trabjar con los tweets: coordenadas (no hace falta decir por qué), texto, importante para hacer minería de datos semántica, id del tweet, el cual me permitirá trabajar para limpiar los tweets repetidos, e idioma del tweet, para hacer clasificaciones, aunque en esta ocasión, todos los devueltos serán en castellano (porque así se lo he indicado en el parámetro)
for tweets in peticion:
    if tweets.geo:
        y= tweets.geo['coordinates'][0]
        x= tweets.geo['coordinates'][1]
        texto= unicode(tweets.text)
        tw_id=tweets.id
        lang=str(tweets.iso_language_code)

        print x, y, unicode(texto), tw_id

Crear la base de datos:

Una vez probado el script, y visto que cumple con lo requerido, he pasado a crear una base de datos Postgis para almacenar todos estos datos. La base de datos sigue el siguiente esquema:
CREATE TABLE geo_tw
(
  id serial NOT NULL,
  id_tweet bigint,
  texto_tw character varying,
  lang character varying,
  x_coord double precision,
  y_coord double precision,
  fecha timestamp with time zone,
  CONSTRAINT geo_tw_pkey PRIMARY KEY (id )
)
Sin entrar mucho en profundidad del lenguaje SQL, he especificado que me cree la tabla geotw, con los campos, id, idtweet, textotw, lang, xcoord, ycoord y fecha. Como véis, el campo fecha no ha sido sacado del propio tweet, que podría haberse sacado con la propiedad .createdat, sino que se ha creado a partir de la función NOW() propia de Postgres. Es decir, que la fecha registrada será la de la entrada del registro en la base de datos, y no la de la creación del tweet. Esto puede generar un pequeño desfase de un minuto, según cada cuanto carguemos las tabla, pero es un detalle ínfimo par ael estudio que nos atañe. Por otro lado, es más fácil trabajar con fechas si están en el formato nativo de Postgres (timestamp) que si hay que hacer transformaciones.

Conectar Python con Postgres:

Tras esto el paso siguiente ha sido crear un “conector” entre el script de Python y la base de datos, para automáticamente registar los tweets en ella. Esto se ha conseguido con suma facilidad con la librería psycopg2 de Python. Las siguientes líneas hacen dicha tarea:
#Me conecto a la base de datos
conn = psycopg2.connect("dbname=twitter host=localhost user=postgres
 password=********")
#Creo el objeto cursor
cur = conn.cursor()
#Dentro del bucle for, ejecuto la función SQL:
cur.execute("INSERT INTO geo_tw (id_tweet, texto_tw ,lang, 
x_coord, y_coord, fecha) VALUES (%s, %s, %s, %s, %s, %s)",(tw_id, 
texto,lang,  x, y, "NOW()"))

#Esto hace que se apliquen los cambios, si no, no se escribirá nada.
conn.commit()

Con todo esto funcionando, seremos capaces de recoger un número de tweets cada vez que corramos el script. Ahora viene la parte del proyecto menos profesional, por decirlo de alguna manera. De momento, como está en fase de pruebas, he utilizado, como he dicho, la API de Twitter Search, lo cual me permite hacer búsquedas por query, radio, etc. Un mejor uso del script sería si hubiera utilizado la API de Stream en lugar de la de Search. La diferencia está en que la API de stream devuelve un nuevo tweet cada vez que se genera, mientras que la de search, devuelve los tweets requeridos cada vez que se ejecuta el script. Como “a grandes males, grandes remedios”, y mientras adapto el script a la API de Streaming, esto se ha solucionado mediante un “Daemon” o demonio. Esto significa que se puede “programar” el script para que se ejecute cada cierto tiempo, y así “emular” a la API de Streaming. Y digo emular, porque habrá que hacer unas cuantas correcciones posteriores que no habría que hacer con el otro método. Así, con el programador de tareas de Ubuntu, tan solo hay que ejecutar el programa cada minuto (o el intervalo que se quiera) para ir rellenando la base de datos.
Hasta aquí tendríamos la primera parte del tutorial. Hemos conseguido tener una base de datos capaz de capturar los tweets generados y guardarlos en nuestro servidor. En la siguiente entrega veremos cómo utilizar la extensión de Postgres PostGIS para dotar la base de datos de geometría, y así poder realizar alguna visualización de los datos.