Post on 25-Jul-2020
Esc
uela
Pol
itécn
ica
Sup
erio
r de
Lin
ares
UNIVERSIDAD DE JAÉN Escuela Politécnica Superior de Linares
Trabajo Fin de Grado
______
HERRAMIENTA PARA LA
EXTRACCIÓN DE OPINIONES EN TWITTER
Alumno: Joaquín Gómez Olías Tutor: Prof. Dña. Mª Dolores Molina González Depto.: Ingeniería de Telecomunicación Tutor: Prof. Dña. Salud Mª Jiménez Zafra Depto.: Ingeniería Informática
Octubre, 2017
1
A QUIEN CONMIGO VA
2
ÍNDICE
1 RESUMEN ..................................................................................................................11
2 INTRODUCCIÓN ........................................................................................................12
2.1 Motivación .......................................................................................................12
2.2 Estructura del documento ................................................................................14
3 OBJETIVOS ................................................................................................................15
4 ESTADO DEL ARTE ...................................................................................................16
4.1 NodeXL ............................................................................................................16
4.2 DiscoverText ....................................................................................................17
5 MATERIALES Y MÉTODOS .......................................................................................18
5.1 Revisión de métodos de acceso a información de Twitter ................................18
5.1.1 Impacto de cambios previstos en Twitter ...........................................18
5.1.2 Formato de la información..................................................................19
5.1.3 Objetos en Twitter ..............................................................................20
5.1.4 APIs de Twitter ...................................................................................22
5.1.4.1 REST API ....................................................................................24
5.1.4.2 Streaming API .............................................................................28
5.1.5 Respuestas API standard ..................................................................32
5.1.6 GNIP ..................................................................................................33
5.1.7 Evolución APIs de Twitter ..................................................................33
5.1.8 Búsqueda Avanzada de Twitter .........................................................34
5.1.8.1 Filtros de búsqueda .....................................................................35
5.1.8.2 Información ofrecida ....................................................................35
5.1.8.3 Web Scraping ..............................................................................36
5.2 Estrategia a seguir para la extracción de tweets ..............................................37
5.3 Información de campos para búsqueda y extracción .......................................38
5.3.1 Información accesible de un tweet .....................................................38
5.3.1.1 Información accesible desde Streaming API ................................38
5.3.1.2 Información accesible desde el Búsqueda Avanzada de Twitter ..42
3
5.3.2 Campos para filtros de búsqueda.......................................................48
5.3.3 Campos a extraer ..............................................................................49
5.4 Estudio de posibles tecnologías para implementar la herramienta ...................50
5.4.1 Arquitectura web ................................................................................50
5.4.1.1 Modelo de dos capas ..................................................................51
5.4.1.2 Modelo de tres capas ..................................................................51
5.4.1.3 Modelo Vista Controlador ............................................................52
5.4.2 FrontEnd ............................................................................................53
5.4.2.1 JQuery y JQuery UI .....................................................................54
5.4.2.2 AngulaJS .....................................................................................54
5.4.2.3 BackBone.js ................................................................................55
5.4.2.4 Ember.js ......................................................................................55
5.4.2.5 ReactJS .......................................................................................55
5.4.2.6 Bootstrap .....................................................................................55
5.4.3 BackEnd ............................................................................................56
5.4.3.1 JavaScript – NodeJS ...................................................................56
5.4.3.2 Java – Spring MVC / Hibernate ...................................................56
5.4.3.3 PHP – Laravel / Symphony ..........................................................57
5.4.3.4 Python – Django / Web2py / Pyramid ..........................................58
5.4.3.5 Web scraping ..............................................................................59
5.4.3.6 Base de datos .............................................................................59
5.4.3.6.1 Tipos de SGBD ................................................................................................ 59
5.4.3.6.2 SGBD NoSQL: MongoDB ................................................................................. 61
5.5 Tecnologías seleccionadas para implementar la herramienta ..........................62
5.5.1 Arquitectura de la herramienta ...........................................................62
5.5.2 FrontEnd de la herramienta ................................................................63
5.5.3 BackEnd de la herramienta ................................................................63
5.5.4 Sistema Operativo: Ubuntu ................................................................65
6 DESARROLLO ............................................................................................................66
6.1 Condiciones de uso de los servicios de Twitter ................................................66
4
6.2 Diseño de datos ...............................................................................................67
6.2.1 Modelo Entidad-Relación ...................................................................67
6.2.2 Modelo de documentos ......................................................................69
6.3 Diseño de la interfaz FrontEnd .........................................................................70
6.3.1 Búsqueda de Tweets .........................................................................71
6.3.2 Visualización de estadísticas .............................................................72
6.3.3 Gestión de dominios ..........................................................................72
6.3.4 Exportación ........................................................................................72
6.3.5 Peticiones AJAX ................................................................................72
6.4 Diseño de API BackEnd ...................................................................................73
6.4.1 Flujos de búsqueda de tweets ............................................................75
6.4.1.1 Búsqueda de tweets en tiempo real .............................................75
6.4.1.2 Búsqueda de tweets en una ventana temporal ............................79
6.4.2 Comunicaciones Apache2 – Django ..................................................82
6.4.3 Explicación práctica del volumen ofrecido por Streaming API ............83
6.4.4 Sistema de logs .................................................................................84
6.4.5 Cifrado SSL .......................................................................................85
6.5 Problemas y Soluciones...................................................................................87
6.5.1 BackEnd ............................................................................................87
6.5.1.1 Streaming API .............................................................................87
6.5.1.1.1 Búsqueda por localización .............................................................................. 87
6.5.1.1.2 Geolocalización de tweets extraídos .............................................................. 89
6.5.1.1.3 Pruebas de estrés ........................................................................................... 93
6.5.1.2 Web scraping ..............................................................................96
6.5.1.2.1 Filosofía inicial: BeautifulSoup4 ..................................................................... 96
6.5.1.2.2 Selenium + PhantomJS ................................................................................... 99
6.5.1.2.3 Incluir / excluir retweets ............................................................................... 103
6.5.1.2.4 Geolocalización de tweets recuperados ....................................................... 104
6.5.1.2.5 Emojis en tweets .......................................................................................... 105
6.5.1.2.6 Pruebas de estrés ......................................................................................... 105
6.5.2 FrontEnd .......................................................................................... 111
5
6.5.2.1.1 Carga dinámica de librería API Google Maps .............................................. 111
6.5.2.1.2 Códigos de idioma en Twitter ....................................................................... 112
7 RESULTADOS Y DISCUSIÓN .................................................................................. 114
8 CONCLUSIONES ..................................................................................................... 121
8.1 Limitaciones ................................................................................................... 122
8.2 Líneas de futuro ............................................................................................. 123
9 GLOSARIO DE TÉRMINOS ...................................................................................... 124
10 ANEXOS ................................................................................................................... 127
10.1 Mensajes de error devueltos por API standard ......................................... 127
10.2 Códigos de error HTTP asociados a Streaming API ................................. 131
10.3 Pasos previos para usar la API de Twitter ................................................ 132
10.4 Generación de certificado SSL con autofirma ........................................... 136
10.5 Instrucciones para la cargar fichero csv generado en Microsoft Excel ...... 137
10.6 Manual de usuario .................................................................................... 137
10.6.1 Ventana Principal ........................................................................... 138
10.6.2 Interfaz de Búsqueda ..................................................................... 139
10.6.2.1 Panel Configuración ................................................................ 140
10.6.2.2 Panel Tema / Dominio ............................................................. 141
10.6.2.3 Panel Opciones de Búsqueda ................................................. 142
10.6.2.4 Panel Geolocalización ............................................................. 144
10.6.2.5 Botones generales ................................................................... 145
10.6.3 Interfaz de Visualización ................................................................ 146
10.6.4 Interfaz de Gestión ......................................................................... 148
10.6.4.1 Panel Dominios ....................................................................... 149
10.6.4.2 Botones Generales .................................................................. 149
10.6.5 Interfaz de Exportación .................................................................. 150
10.6.5.1 Panel Filtrado de datos ............................................................ 150
10.6.5.2 Panel Selección de campos..................................................... 152
10.6.5.3 Panel Formato descarga ......................................................... 153
10.6.5.4 Botones generales ................................................................... 153
6
10.7 Manual de instalación ............................................................................... 154
10.7.1 Contenido del entregable ............................................................... 154
10.7.2 Requisitos mínimos ........................................................................ 157
10.7.3 Instalación de dependencias .......................................................... 157
10.7.3.1 Python 2.7.13 .......................................................................... 157
10.7.3.2 MongoDB ................................................................................ 158
10.7.3.3 PyMongo ................................................................................. 162
10.7.3.4 Dateutil .................................................................................... 162
10.7.3.5 Tweepy .................................................................................... 162
10.7.3.6 BeautifulSoup4 ........................................................................ 162
10.7.3.7 Selenium ................................................................................. 163
10.7.3.8 PhantomJS .............................................................................. 163
10.7.3.9 Geopy ...................................................................................... 163
10.7.3.10 Dataparser ............................................................................. 163
10.7.3.11 Apache2 ................................................................................ 163
10.7.3.12 Django ................................................................................... 165
10.7.3.13 Módulo WSGI ........................................................................ 165
10.7.4 Instalación de fuentes .................................................................... 166
10.7.4.1 Creación de proyecto Django .................................................. 166
10.7.4.2 Insalación de fuentes ............................................................... 167
10.7.4.3 Configuración para ejecutar en la misma máquina .................. 169
10.7.5 Arranque de servidores .................................................................. 170
11 REFERENCIAS BIBLIOGRÁFICAS .......................................................................... 171
7
ÍNDICE DE FIGURAS
Figura 1: Ejemplo de estructura JSON de un objeto en Twitter ............................20
Figura 2: Ejemplo de Tweet ..................................................................................21
Figura 3: Ejemplo de User ....................................................................................22
Figura 4: Flujo de trabajo de REST API ................................................................25
Figura 5: Flujo de trabajo de Streaming API .........................................................29
Figura 6: Búsqueda Avanzada de Twitter .............................................................34
Figura 7: Ejemplo de búsqueda en Búsqueda Avanzada de Twitter .....................36
Figura 8: Futura estructura de un tweet ................................................................41
Figura 9: Detección de un tweet mediante web scraping ......................................42
Figura 10: Detección de retweet mediante web scraping ......................................43
Figura 11: Detección del ID de un tweet mediante web scraping ..........................43
Figura 12: Detección del ID de un retweet mediante web scraping .......................43
Figura 13: Detección del ID dentro de retweet mediante web scraping .................43
Figura 14: Detección del ID del autor de un tweet mediante web scraping ...........44
Figura 15: Detección del ID del autor de un retweet mediante web scraping ........44
Figura 16: Detección del nombre del autor de un tweet mediante web scraping ...44
Figura 17: Detección del nombre del autor de un retweet mediante scraping .......45
Figura 18: Detección de alias del autor mediante web scraping ...........................45
Figura 19: Detección del alias del autor de un retweet mediante web scraping ....45
Figura 20: Detección del texto de un tweet mediante web scraping ......................45
Figura 21: Detección del idioma de un tweet mediante web scraping ...................46
Figura 22: Detección de fecha de creación de un tweet mediante scraping ..........46
Figura 23: Detección del número de likes de un tweet mediante web scraping ....46
Figura 24: Detección del número de likes de un tweet mediante web scraping ....47
Figura 25: Detección del nº de respuestas de un tweet mediante web scraping ...47
Figura 26: Detección de los hastags de un tweet mediante web scraping ............47
Figura 27: Detección de menciones en un tweet mediante web scraping .............47
Figura 28: Detección de cita a otro tweet en un tweet mediante web scraping .....48
Figura 29: Modelo de aquitectura web de 2 capas ...............................................51
Figura 30: Modelo de aquitectura web de 3 capas ...............................................52
Figura 31: Modelo Vista Controlador ....................................................................53
Figura 32: Térrminos de servicio de Twitter ..........................................................66
Figura 33: Modelo Entidad-Relación tweets .........................................................68
Figura 34 : Modelo Entidad-Relación usuarios .....................................................69
Figura 35: Modelo de documento tipo TWEETS ...................................................70
8
Figura 36: Modelo de documento tipo USUARIOS ...............................................70
Figura 37: Estructura Herramienta extracción de opniones de Twitter ..................74
Figura 38: Diagrama de flujo de búsqueda de tweets en tiempo real ....................76
Figura 39: Diagrama de flujo de búsqueda de tweets en ventana temporal ..........80
Figura 40: Ejemplo de traza de error ....................................................................85
Figura 41: Ejemplo de traza de inicio de petición ..................................................85
Figura 42: Ejemplo de traza con cálculo tiempo total empleado ...........................85
Figura 43: Problemas búsqueda por localizacion (I) .............................................88
Figura 44: Problemas búsqueda por localizacion (II) ............................................88
Figura 45: Problemas búsqueda por localizacion (III) ...........................................89
Figura 46: Problemas búsqueda por localizacion (IV) ...........................................89
Figura 47: Problemas geolocalización de tweets extraídos (I) ..............................90
Figura 48 Problemas geolocalización de tweets extraídos (II) ..............................90
Figura 49 Problemas geolocalización de tweets extraídos (III) .............................91
Figura 50: Pruebas de estrés Streaming API (I) ...................................................94
Figura 51: Pruebas de estrés Streaming API (II) ..................................................94
Figura 52: Pruebas de estrés Streaming API (III) .................................................96
Figura 53: Problemas scraping BeautifulSoup (I) ..................................................97
Figura 54: Problemas scraping BeautifulSoup (II) .................................................97
Figura 55: Problemas Selenimum + Phantom (I) ................................................ 100
Figura 56: Problemas Selenimum + Phantom (II) ............................................... 101
Figura 57: Problemas Selenimum + Phantom (III) .............................................. 102
Figura 58: Problemas Selenimum + Phantom (IV) .............................................. 102
Figura 59: Geolocalización de tweets con scraping ............................................ 104
Figura 60: Emojis en tweets ............................................................................... 105
Figura 61: Pruebas de estrés scraping (I) ........................................................... 106
Figura 62: Pruebas de estrés scraping (II) .......................................................... 107
Figura 63: Pruebas de estrés scraping (III) ......................................................... 107
Figura 64: Pruebas de estrés scraping (IV) ........................................................ 108
Figura 65: Pruebas de estrés scraping (V) ......................................................... 109
Figura 66: Pruebas de estrés scraping (VI) ........................................................ 110
Figura 67: Pruebas de estrés scraping (VII) ....................................................... 110
Figura 68: Pruebas de estrés scraping (VIII) ...................................................... 110
Figura 69: Pruebas de estrés scraping (IX) ........................................................ 111
Figura 70: Pruebas de estrés scraping (X) ......................................................... 111
Figura 71: Campos fichero ................................................................................. 115
Figura 72: Términos de búsqueda ...................................................................... 115
9
Figura 73 Resultados búsqueda ......................................................................... 115
Figura 74: Parámetros fechas ............................................................................ 116
Figura75: Resultados fecha ................................................................................ 116
Figura 76: Resultado tweets ............................................................................... 116
Figura 77: Resultado exportación ....................................................................... 117
Figura 78: Filtro geolocalización ......................................................................... 118
Figura 79: Resultados geolocalización ............................................................... 118
Figura 80: Estadísticas globales ......................................................................... 118
Figura 81: Estadísticas parciales ........................................................................ 119
Figura 82: Gestión de dominios .......................................................................... 119
Figura 83: Configuración credenciales................................................................ 120
Figura 84: Cifrado SSL ....................................................................................... 120
Figura 85: Códigos Error API standard (I) ........................................................... 127
Figura 86: Códigos Error API standard (II) .......................................................... 128
Figura 87: Códigos Error API standard (III) ......................................................... 129
Figura 88: Códigos Error API standard (IV) ........................................................ 130
Figura 89: Códigos de error HTTP asociados a Streaming API (I) ...................... 131
Figura 90: Códigos de error HTTP asociados a Streaming API (II) ..................... 132
Figura 91: Acceso a la interfaz de aplicaciones .................................................. 133
Figura 92: Interfaz de aplicaciones ..................................................................... 133
Figura 93: Formulario para crear una aplicación ................................................. 134
Figura 94: Generación de claves y tokens de acceso ......................................... 135
Figura 95: Ventana Principal .............................................................................. 138
Figura 96: Panel de navegación ......................................................................... 138
Figura 97: Indicadores de ventana ..................................................................... 139
Figura 98 Etiqueta inormativa ............................................................................. 139
Figura 99: Botones Mostrar todo/Ocultar todo .................................................... 139
Figura 100: Interfaz de Búsqueda ....................................................................... 140
Figura 101: Panel Configuración ........................................................................ 140
Figura 102: Botón Guardar configuración ........................................................... 141
Figura 103: Botón Eliminar configuración ........................................................... 141
Figura 104: Cargar configuración ....................................................................... 141
Figura 105: Editar configuración ......................................................................... 141
Figura 106: Panel Tema / Dominio ..................................................................... 142
Figura 107: Panel Opciones de Búsqueda ......................................................... 142
Figura 108: Panel de Geolocalización ................................................................ 144
Figura 109: Botón Buscar localización ................................................................ 144
10
Figura 110: Botón Buscar coordenadas .............................................................. 145
Figura 111: Botón Limpiar configuración geolocalización ................................... 145
Figura 112: Botón Aceptar configuración de geolocalización .............................. 145
Figura 113: Botón Cancelar configuración de geolocalización ............................ 145
Figura 114: Botón Ejecutar búsqueda ................................................................ 146
Figura 115: Botón Limpiar Opciones de Búsqueda ............................................. 146
Figura 116: Interfaz de Visualización .................................................................. 147
Figura 117: Botón Refrescar información ........................................................... 147
Figura 118: Panel Estadísticas Globales ............................................................ 148
Figura 119: Panel Estadísticas Colección ........................................................... 148
Figura 120: Interfaz de Gestión .......................................................................... 149
Figura 121: Botón Refrescar información ........................................................... 149
Figura 122: Botón Eliminar dominios .................................................................. 150
Figura 123: Interfaz de Exportación .................................................................... 150
Figura 124: Panel Filtrado de Datos ................................................................... 151
Figura 125: Botón Limpiar filtros ......................................................................... 152
Figura 126: Botón Calcular estadísticas ............................................................. 152
Figura 127: Panel Selección de Campos ............................................................ 152
Figura 128: Botón Control de selección de campo ............................................. 153
Figura 129: Botones de activación/desactivación masiva ................................... 153
Figura 130: Panel Formato descarga ................................................................. 153
Figura 131: Botón Limpiar opciones de exportación ........................................... 153
Figura 132: Botón Exportar tweets ..................................................................... 154
Figura 133: Mensaje de confimación descarga de fichero .................................. 154
Figura 134: Contenido entregable aplicación ...................................................... 155
Figura 135: Fuentes apache ............................................................................... 155
Figura 136: Fuentes recotweets ......................................................................... 156
Figura 137: Fuentes tfg ...................................................................................... 156
Figura 138: Instalación Python ........................................................................... 158
Figura 139: Instalación MongoDB (I) .................................................................. 159
Figura 140: Instalación MongoDB (II) ................................................................. 160
Figura 141: Instalación MongoDB (III) ................................................................ 162
Figura 142: Comprobación acceso a Django desde Python ............................... 165
Figura 143 : Creación proyecto Django .............................................................. 166
Figura 144 Aplicación Django ............................................................................ 167
11
1 RESUMEN
En los últimos años, debido a la evolución experimentada por la web hacia la
comúnmente conocida como Web 2.0, el usuario, que por lo general asumía el rol de mero
espectador que consume información, ha pasado a tomar protagonismo para convertirse,
además, en fuente constante de información que interactúa con el resto de usuarios
creando y gestionando contenidos a través de su carácter colaborativo. Con este propósito,
han surgido diversas plataformas de comunicación a través de la web: foros, redes
sociales, blogs, wikis, etc. En este sentido, las opiniones que los usuarios vierten en la web,
constituyen una inagotable fuente de información en un amplio abanico de ámbitos
(comercio, turismo, política, etc.) a través de la aplicación de técnicas de Procesamiento
del Lenguaje Natural.
Twitter, lanzado en julio de 2006 como un servicio en el que los usuarios publican
opiniones (tweets) con una extensión máxima de 140 caracteres, se ha convertido en la
red social con formato de microblogging más extendida, con alrededor de 328 millones de
usuarios activos.
El presente trabajo aborda el proceso de extracción de opiniones de Twitter, para
la creación de corpus de información, como etapa previa dentro del Procesamiento del
Lenguaje Natural. Para ello, se ha analizado el funcionamiento de las APIs y soluciones
ofrecidas por Twitter, así como la información a extraer que potencialmente podría ser útil
para su posterior procesado y, finalmente, se ha desarrollado una herramienta para la
automatización de la extracción de tweets.
12
2 INTRODUCCIÓN
En este trabajo se ha desarrollado una herramienta para la extracción, de forma
automatizada, de opiniones de Twitter. Para ello ha sido necesario realizar un estudio
previo de los tipos de acceso ofrecidos por Twitter a través de sus APIs (Application
Programming Interface), así como de la información disponible acerca de los tweets, que
permitan definir un modelo común para el tratamiento y almacenamiento de la información
extraída.
La herramienta desarrollada permite definir colecciones de tweets a través filtros de
búsqueda acordes a la información accesible, de forma que pueda acotarse el volumen de
tweets obtenidos en función de la precisión de su contenido: términos que aparecen en el
texto de cada tweet, idioma, si se trata de tweets originales o si son retweets de otros, fecha
de creación y su localización.
Por otra parte, la herramienta también proporciona estadísticas de las colecciones
almacenadas en base de datos en relación al volumen de tweets que las conforman,
volumen de tweets por idioma y por localización. Además, permite eliminar colecciones, y
configurar y aplicar filtros para exportar tweets a ficheros con formato txt o csv.
2.1 Motivación
El Procesamiento del Lenguaje Natural (PLN), como parte importante de la
Inteligencia Artificial (IA), ha permitido el desarrollo de complejos métodos de computación
para el tratamiento de la información a través del lenguaje [1] con campos de aplicación
variados. Por ejemplo:
• Traducción Automática
• Reconocimiento de Voz
• Síntesis de Voz
• Generación de Lenguajes Naturales
• Búsqueda de respuestas
• Recuperación de información
• Extracción de información
13
Con la llegada de la Web 2.0 [2] y la eclosión de plataformas y servicios que facilitan
la comunicación, generación e intercambio de contenidos de naturaleza heterogénea entre
los usuarios, así como la diversificación de los dispositivos de acceso a la red de redes, el
volumen de usuarios e información generada ha aumentado considerablemente en los
últimos años. Como dato, según el Informe Mobile en España y en el Mundo 2017, de
Ditrendia [3], sólo a través de dispositivos móviles, se estima que, en 2017, en torno a 1.9
mil millones de usuarios acceden a diario a redes sociales, lo que supone un 34% respecto
del total de la población mundial y un incremento del 7% respecto al 2016.
Esta nueva forma de entender la web ha convertido al usuario en una fuente de
información constante e inagotable, cuyas opiniones y publicaciones instantáneas
constituyen un nicho informativo con aplicación en multitud de sectores (publicidad,
turismo, tecnología, política, economía, cine, etc.), y cuya explotación es el principal
objetivo de aplicaciones orientadas a la extracción de información subjetiva, como es el
caso del Análisis de Sentimientos (AS) o Minería de Opiniones (MO) [4], que clasifica un
texto en función de la polaridad de la opinión expresada por su autor. Los resultados de
este procesamiento de las opiniones permiten, por ejemplo, cuantificar el grado de
satisfacción o disconformidad de un producto o servicio tanto en la venta como en la
postventa, anticipar posibles comportamientos o reacciones de la población ante la toma
de decisiones por parte de una entidad (gobierno, empresa, etc.), etc.
Actualmente, una de las principales fuentes de corpus de opiniones empleadas por
la comunidad científica es la red social Twitter [5], debido al volumen de información y a
aspectos sociológicos derivados de su carácter divulgativo, como el impacto que tiene en
política, economía y eventos sociales, entre otros [6]. Esta red social, ideada por Jack
Dorsey en 2006 [7], es un servicio de microblogging en el que los usuarios pueden publicar
mensajes cortos (tweets) de contenido libre, con una extensión máxima de 140 caracteres.
Se estima que la plataforma cuenta con alrededor de 328 millones de usuarios activos, que
generan un volumen de tweets superior a los 500 millones diarios [8].
El presente trabajo aporta una solución a la extracción de tweets para la generación
de corpus de información, mediante el desarrollo de una herramienta independiente que
facilite su automatización a través de un entorno visual sencillo. La generación de corpus
es una parte básica por su condición de fuente de información para cualquier tarea de
procesamiento. Además, la precisión de su contenido, relativa a contener información
exclusiva en relación a un tema o dominio, influye de forma directa en la calidad de los
resultados obtenidos del procesado que sobre ellos se realice.
14
2.2 Estructura del documento
A continuación, se describe a modo de guía, cada uno de los apartados que
conforman el presente documento:
• Resumen: Breve descripción del objeto del presente trabajo.
• Introducción: Breve descripción de las funcionalidades de la herramienta
desarrollada y motivación del trabajo.
• Objetivos: Descripción de los objetivos perseguidos.
• Estado del Arte: Descripción de soluciones actualmente empleadas para la
extracción de opiniones de Twitter.
• Materiales y Métodos: Descripción de las herramientas empleadas para el
desarrollo de la herramienta (APIs, tecnologías empleadas, etc)
• Desarrollo: Descripción del diseño e implementación de la herramienta, incluyendo
los problemas detectados durante la implementación y las soluciones empleadas
para solucionarlos.
• Resultados y Discusión: Descripción de los resultados obtenidos a la finalización
del desarrollo de la herramienta.
• Conclusiones: Exposición de las ideas finales derivadas del desarrollo, evaluación
de resultados obtenidos con respecto a los esperados, así como posibles líneas de
futuro de cara a posibles versiones mejoradas de la herramienta.
• Anexos: Manuales de instalación y de usuario.
• Glosarios: Catálogo de términos útiles y su descripción para la correcta
comprensión del contenido de este documento.
• Referencias Bibliográficas: Reseñas de las fuentes empleadas en la elaboración
del presente documento.
15
3 OBJETIVOS
Los objetivos planteados al comienzo de este trabajo son los siguientes:
1. Ayudar a comprender las posibilidades ofrecidas por la información generada por
usuarios de plataformas colaborativas, en este caso Twitter, centrándose, dentro
del PLN, en la fase previa de conformación de corpus de información a partir de la
extracción de colecciones de tweets.
2. Analizar el funcionamiento de las APIs de Twitter para el acceso a la información
incluida en los tweets, y determinar la metodología a seguir para su uso.
3. Analizar el tipo de información ofrecida por Twitter y determinar la información de
interés para ser extraída.
4. Desarrollar una herramienta que automatice la extracción de tweets a partir de los
resultados obtenidos en los análisis definidos en los objetivos previos.
16
4 ESTADO DEL ARTE
Actualmente, la mayoría de las soluciones desarrolladas para la extracción de
tweets hacen uso de las APIs ofrecidas por Twitter y se incluyen como funcionalidades
dentro de paquetes comerciales destinados, normalmente, al análisis de redes sociales
(Social Network Analysis); o bien, se implementan ad hoc de forma personalizada como
parte del desarrollo de herramientas privadas, habitualmente enmarcadas en el ámbito
científico/experimental y destinadas a realizar labores de PLN [9]; siendo muy bajo o
prácticamente nulo el porcentaje de las que simplemente están destinadas a la
recuperación y exportación de tweets, como es el caso de la herramienta desarrollada en
este trabajo. A continuación, se presentan algunas de las soluciones comercializadas.
4.1 NodeXL
NodeXL [10], cuya primera versión fue publicada en julio de 2008, es un plugin
desarrollado por Social Media Reserarch Foundation que se instala como plantilla open-
source para Microsoft Excel en sus versiones 2007, 2010, 2013 y 2016. Ofrece servicios
de análisis de redes sociales a través de la importación de gráficos procedentes de
aplicaciones externas (GraphML, Pajek, UCINet), o a través de la conexión directa a APIs
de redes sociales (Twitter, Facebook, Youtube, Flickr).
El paquete es comercializado en dos formatos: NodeXL Basic, gratuito y con
características limitadas; y NodeXL Pro, sujeto al pago de una licencia que proporciona
acceso a todas sus funcionalidades.
Con respecto a la extracción de tweets, la herramienta permite filtrar la búsqueda
de tweets por términos en el texto y por usuario, accediendo a la información de Twitter a
través de su REST API, que no proporciona acceso a tweets con más de 7 días de
antigüedad. Por otra parte, establece límites de descarga que difieren según la versión
instalada:
• Basic: 2.000 tweets como máximo
• Pro: 18.000 tweets como máximo
17
Si se desea incrementar el volumen de tweets más allá de los límites predefinidos,
el paquete ofrece la posibilidad de acceder a datos ofrecidos por proveedores externos,
aunque esta solución encarece más el precio final del paquete.
4.2 DiscoverText
Desarrollado por Texsifter [11], se trata de un paquete de software propietario
basado en la nube, que ofrece un servicio de análisis de textos mediante uso de técnicas
de búsqueda, filtrado, detección de duplicados, codificación humana y machine-learning.
Se trata de una herramienta de pago orientada principalmente a empresas, aunque admite
perfiles profesionales y académicos. Oferta un período de prueba de 3 días con algunas
de sus principales funcionalidades.
El módulo de recolección de datos soporta la conectividad directa con redes
sociales como Facebook y Twitter a través de sus APIs nativas. También admite como
fuentes, colecciones de emails procedentes de servidores Exchange y Outlook, y está
integrado con SurveyMonkey [12] (empresa dedicada a la generación de encuestas online).
En el caso de Twitter, la extracción de tweets se realiza en su módulo Sifter, a través de
la plataforma de pago GNIP de Twitter, que proporciona soluciones comerciales de acceso
premium a todo el histórico de datos de Twitter. Se dispone de un período de 30 días para
procesar los resultados de la búsqueda. Finalizado dicho período, estos datos son
eliminados.
18
5 MATERIALES Y MÉTODOS
En este apartado se realiza un análisis previo de los métodos disponibles para el
acceso y recuperación de la información en Twitter, la información accesible mediante
dichos métodos, la estrategia final a seguir para la extracción de tweets, y las herramientas
empleadas para acometer el desarrollo de una aplicación que automatice la extracción de
tweets.
5.1 Revisión de métodos de acceso a información de Twitter
5.1.1 Impacto de cambios previstos en Twitter
Con fecha del 06/04/2017, Twitter anunció la unificación de su plataforma API (APIs
públicas, GNIP, etc.) [13], lo que supondrá la redefinición de las actuales APIs y la creación
de nuevos endpoints (métodos de acceso) que faciliten a los desarrolladores el acceso a
la información generada en Twitter.
Estos y otros cambios comenzarán a implementarse durante los próximos meses y
a lo largo del próximo año. Para ello, han elaborado una hoja de ruta [14] en la que se irán
incluyendo a modo de resumen todas las iniciativas y cambios previstos.
De cara al presente trabajo, no será posible evaluar el impacto que estos cambios
tendrán hasta que Twitter implemente dichos cambios y comunique, a través de la
documentación técnica oportuna, la compatibilidad con el parque de aplicaciones
desarrolladas que actualmente hace uso de sus APIs.
Con fecha del 25/09/2017, y con el desarrollo del presente trabajo prácticamente
finalizado, Twitter ha anunciado, como primera fase dentro de la estrategia de unificación
de sus plataformas API, el lanzamiento de su nueva plataforma de desarrollo
https://developer.twitter.com/ como nuevo punto de referencia técnica y documental de sus
nuevos recursos de desarrollo (APIs, entidades, relaciones, etc.), que reemplaza a las
hasta ahora existentes https://gnip.com y https://dev.twitter.com [15].
Toda la información recopilada, analizada, y empleada como base de
implementación en el presente trabajo, se corresponde con la ofrecida por las plataformas
de desarrollo de Twitter previas al reciente nuevo lanzamiento del 25/09/2017.
19
A fecha de cierre del presente documento, Twitter no ha publicado un deadline para
la deprecación de sus actuales APIs y endpoints, por lo que la información ofrecida en este
trabajo mantendrá su carácter vigente hasta la fecha límite que Twitter anuncie
oportunamente.
5.1.2 Formato de la información
La información gestionada por las APIs de Twitter está codificada en formato JSON
(JavaScript Object Notation). Este formato, que actualmente está muy extendido para el
intercambio de datos, se caracteriza porque la información se estructura en parejas
clave:valor [16].
En Twitter, los atributos y sus valores se organizan en objetos que conforman las
unidades básicas de gestión, intercambio y almacenamiento de la información. En la Figura
1 se adjunta la estructura JSON de un objeto en Twitter, en la que cada atributo tiene un
valor asignado, o, en algunos casos, otro subconjunto (diccionario) de parejas clave:valor,
o una lista de valores (Figura 1).
20
Figura 1: Ejemplo de estructura JSON de un objeto en Twitter
Fuente: Twitter Developers [17]
5.1.3 Objetos en Twitter
Las APIs de Twitter trabajan con los siguientes tipos básicos de Objetos [17], cuyos
atributos difieren según el tipo de objeto:
• Tweet: También conocido como “status update”, es la unidad básica de Twitter y
puede ser objeto padre de los objetos User y Entities. Un Tweet puede contener
alrededor de 140 atributos asociados, siendo sus atributos básicos id (identificador
de tweet), create_at (fecha de creación) y text (texto del tweet). Además, este objeto
puede ser integrado (incorporado junto a otros elementos (video, imágenes, links,
etc)), retweeteado, citado, replicado, marcado como favorito, desmarcado de
favoritos, y eliminado. En la Figura 2 se adjunta un ejemplo de visualización de un
Tweet a través de la interfaz gráfica de Twitter.
21
Figura 2: Ejemplo de Tweet
Fuente: Twitter [5]
• User: Objeto que describe al autor de un Tweet. Contiene información de su cuenta
pública en Twitter. Un usuario puede ser alguien o algo. Este objeto puede crear
tweets, retweetear, citar tweets, seguir a otros usuarios, crear listas, tienen un muro
(timeline), pueden ser mencionados y pueden ser buscados. En la Figura 3 se
adjunta un ejemplo de visualización de un User a través de la interfaz gráfica de
Twitter.
22
Figura 3: Ejemplo de User
Fuente: Twitter [5]
• Entities: Objetos que se relacionan con el resto de tipos de objetos aportando
información extra sobre el contenido de la información tweeteada. Esta información
añadida puede ser imágenes, videos, GIFs, hastags, urls, menciones etc.
• Geospatial: Objetos que contienen información de geolocalización. La localización
puede estar especificada por unas coordenadas geográficas exactas (longitud y
latitud), obtenidas durante la generación de un Tweet, o bien, por un objeto Place
formado, entre otros campos, por un nombre de localización y un bounding box
(área con forma poligonal, definida por varios puntos de coordenadas, usualmente
un cuadrado) que describe un área geográfica determinada. La información del
objeto Place es obtenida a partir de la selección, por el propio usuario a través de
la interfaz de Twitter, de un nombre de localización geográfica a la que asociar los
Tweets generados desde su cuenta de usuario.
En el apartado 5.3.1 Información accesible de un tweet del presente documento se
abordará con detalle los campos incluidos en los objetos de tipo Tweet, sobre el que se
centra la búsqueda y extracción de información en la herramienta implementada en este
trabajo.
5.1.4 APIs de Twitter
23
Las APIs son accesibles a través peticiones HTTP en las que definen las acciones
a ejecutar sobre los endpoints/recursos accedidos. Twitter proporciona un conjunto de
endpoints o métodos de acceso para gestionar la información disponible, accesibles según
la API a la que se acceda. Cada endpoint está definido por los siguientes valores.
• URL de recurso: URL que identifica al recurso al que se accede con formato JSON.
Por ejemplo, para el acceso al endpoint POST statuses/filter, que permite definir
filtros para conformar una query de búsqueda de tweets, la URL del recurso es:
https://stream.twitter.com/1.1/statuses/filter.json
• Información de recurso: Especifica el formato de respuesta en las peticiones
realizadas (normalmente JSON), si requiere autenticación, y si la tasa de peticiones
tiene un límite definido.
• Parámetros: Parámetros para el acceso al recurso
Se distinguen dos tipos de familias de APIs [18] en función del libre acceso a sus
funcionalidades:
• APIs standard: APIs públicas de acceso gratuito con condiciones limitadas uso y
acceso a la información.
• Ads API: APIs de pago orientadas a negocios que permiten crear y gestionar
campañas de marketing en Twitter.
Dentro de las APIs gratuitas, existen dos tipos básicos para interactuar con la
información incluida en los tweets: REST API (para el acceso al histórico de tweets) y
Streaming API (para el acceso al flujo de tweets en tiempo real) [19]. En ambos casos y
desde la versión API v1.1 se requiere autenticación.
Twitter implementa dos tipos de autenticación para el acceso a sus APIs [20]:
• User o application-user authentication: Identifica a una aplicación a través de los
permisos concedidos a un usuario final haciendo uso del protocolo de autorización
OAuth v1.0a, que proporciona acceso limitado a través de un servicio HTTP. Para
24
poder acceder a las APIs y realizar llamadas a sus funciones son necesarios tokens
de acceso al protocolo OAuth, que serán emitidos en nombre de un usuario o una
aplicación dependiendo de la API y la funcionalidad que se desee implementar. Al
solicitar una conexión en nombre de un usuario, este es redirigido para que Twitter
autorice a la aplicación, devolviendo tokens de acceso que no expiran mientras el
usuario no los revoque. Este tipo de autenticación puede ser empleado para el
acceso tanto a REST API como a Streaming API.
• Application-only authentication: Identifica a una aplicación para acceder a las APIs
en su propio nombre, sin usar un contexto de usuario. En este caso, cualquier
petición realizada que requiera un contexto de usuario, por ejemplo, crear un tweet,
no funcionará. Este tipo de autenticación sólo puede ser empleado para el acceso
a REST API.
Por otra parte, Twitter ofrece una colección de librerías (algunas desarrolladas y
soportadas como propias) asociadas a diferentes tecnologías de programación (Java, ASP,
C++, Python, etc.) que permiten trabajar con sus APIs [21], lo que permite al desarrollador
abstraerse del proceso de autenticación, conexión y uso directo de los métodos de cada
API. Para la implementación de la herramienta desarrollada en este trabajo, se ha hecho
uso, como se indica más adelante, de una librería específica para el acceso a las APIs.
5.1.4.1 REST API
Basada en los principios de arquitectura REST (Representational State Transfer)
en la que el acceso a los recursos se realiza a través de su URI (Uniform Resource
Identifier), ofrece un acceso a los datos de Twitter (perfil de usuario, tweets, información de
seguidores, etc) en modo lectura y escritura [22]. Las peticiones realizadas a la API se
encapsulan en peticiones HTTP independientes, tal y como se observa en la Figura 4.
25
Figura 4: Flujo de trabajo de REST API
Fuente: REST API [22]
Además, establece límites en la tasa de peticiones a la API permitidas, basados en
ventanas temporales de 15 minutos [23]. Estos límites se aplican por token de usuario si el
acceso se realiza por medio de user authentication, lo que significa que, si a la misma
aplicación se accede con usuarios distintos, los límites se establecen por cada usuario
individual; o bien, se aplican globalmente por aplicación si el acceso se realiza por medio
de application-only authentication. La información estadística de las tasas de peticiones se
incluye en la propia cabecera de respuesta HTTP a través de los campos:
• x-rate-limit-limit: tasa de peticiones límite para un endpoint dado.
• x-rate-limit-remaining: número de peticiones restantes para la ventana de 15
minutos en curso.
• x-rate-limit-reset: tiempo restante en segundos de la ventana antes del reseteo de
la tasa en curso.
Para cada endpoint/recurso se define una tasa de peticiones límite específica,
aplicándose por defecto un límite de 15 peticiones cada 15 minutos en los casos no
definidos. En caso de superarse un límite establecido, la API devuelve un mensaje de error
en la respuesta HTTP correspondiente, advirtiendo dicha circunstancia. En el apartado
5.1.5 Respuestas API standard se recogen, para su consulta, los mensajes de error
devueltos por la API, pudiéndose consultar el mensaje específico relativo al caso en que
se exceda una tasa de peticiones límite establecida.
26
Dentro de esta API, se definen, a su vez, las siguientes APIS, en función de la
especialización en componentes o tareas específicas:
• Search API: permite realizar una query de búsqueda específica de tweets.
• Media API: permite interaccionar con objetos media (representan fotos, videos o
GIFs animados, etc) que pueden ser incluidos en tweets, perfiles de usuario, etc.
• Curator AP: permite a los distribuidores de contenido ofrecer sus contenidos de
forma organizada.
• TON (Twitter Object Nest) API: permite la subida de contenidos multimedia a
Twitter.
De estas, la de mayor utilidad para el propósito de este trabajo es Search API [24].
Esta ofrece una experiencia de búsqueda similar (pero no igual) a la herramienta de
búsqueda incluida en la propia aplicación de Twitter, permitiendo definir una query o filtro
para la búsqueda de tweets, obteniéndose tweets importantes y/o recientes, siempre dentro
del espacio temporal delimitado por los últimos 7 días.
Search API define los siguientes endpoints:
• GET search/tweets: establece una query específica y recupera una colección de
tweets, coincidentes con los criterios de búsqueda. Los tweets recuperados
pertenecen al conjunto de tweets clasificados por la API como importantes.
• GET saved_searches/list: recupera las querys de las consultas realizadas por el
usuario autenticado.
• GET saved_searches/show/:id: recupera la información para una búsqueda
salvada, identificada por un id. El usuario autenticado debe ser el propietario del ID
de búsqueda.
• POST saved_searches/créate: Crea una nueva búsqueda guardada por el usuario
autenticado. Establece un límite de 25 búsquedas guardadas por usuario.
27
• POST saved_searches/destroy/:id: Elimina una búsqueda guardada por el usuario
autenticado, identificada por un id. El usuario autenticado debe ser el propietario de
la búsqueda guardada.
De los endpoints definidos, el indicado para la búsqueda de tweets es GET
search/tweets. Este endpoint está definido por los siguientes valores.
• URL de recurso: https://api.twitter.com/1.1/search/tweets.json
• Información de recurso: Respuesta en formato JSON, requiere autenticación y
establece los siguientes límites de tasa de peticiones:
� 180 peticiones/ventana 15 minutos para aplicaciones autenticadas con user
auth (user authentication).
� 450 peticiones/ventana 15 minutos para aplicaciones autenticadas con app
auth (application authentication)
• Parámetros: Parámetros para el acceso al recurso:
� q: Parámetro obligatorio que define la query de búsqueda con 500
caracteres como máximo, codificados en UTF-8.
� geocode: Parámetro opcional para recuperar tweets localizados dentro de
un radio dado, definido por las coordenadas de latitud/longitud.
� lang: Parámetro opcional para filtrar tweets según un código idioma
determinado, acorde con el estándar ISO-639-1 [25].
� locale: Parámetro opcional, especifica el idioma empleado en la query de
búsqueda, definida en el parámetro q.
� result_type: Parámetro opcional, especifica qué tipo de resultados se
prefiere recibir: mixed (tweets populares y tweets recientes), recent (sólo los
tweets más recientes), popular (sólo los tweets más populares).
28
� count: Parámetro opcional, especifica el número de tweets a recuperar por
página (en el caso de ser numerosos, los resultados se devuelven
paginados) hasta un máximo de 100.
� until: Parámetro opcional, recupera tweets creados antes de una fecha
dada, hasta un máximo de 7 días previos desde el momento de ejecución
de la consulta. La fecha sigue el formato YYYY-MM-DD.
� since_id: Parámetro opcional, recupera tweets con ID mayor que el
especificado, pudiendo ID tener, como máximo, el valor del ID disponible
más antiguo.
� max_id: Parámetro opcional, recupera tweets con ID menor o igual que el
especificado.
� include_entities: Parámetro opcional, si su valor es true, los resultados
incluirán atributos de entities.
Los parámetros descritos conforman un conjunto de operadores más amplio que el
ofrecido por Streaming API, permitiendo establecer mejores filtros de búsqueda. Sin
embargo, no recupera todos los tweets, sino los más relevantes y/o recientes de los
definidos en la búsqueda, por lo que, si lo que se desea es recuperar sólo los tweets más
recientes, Twitter recomienda el uso de la Streaming API [24].
5.1.4.2 Streaming API
Permite el acceso a flujos de datos en tiempo real o muy reciente en Twiter,
denominados streams. A diferencia de REST API, es necesario mantener abierta una
conexión HTTP (a través de la cabecera keep-alive en la petición), y recuperar la respuesta
de forma incremental, lo que permite la descarga indefinida de información a través de la
misma conexión HTTP [26].
En la conexión a Streaming API, la petición HTTP se realiza a un endpoint
determinado, incluyendo en dicha petición, a parte de la cabecera de autorización requerida
por el protocolo OAuth, los parámetros definidos para dicho endpoint. Una vez realizada la
conexión, Twitter envía a la aplicación los tweets generados (incluyendo retweets) a través
29
de la conexión establecida y mantenida con el endpoint [26], tal y como se observa en la
Figura 5.
Figura 5: Flujo de trabajo de Streaming API
Fuente: Streaming API [26]
La conexión se mantiene viva mientras la API devuelve información. Si durante una
conexión, la API no detecta información que servir durante un período de 90 segundos,
enviará un mensaje keep-alive cada 30 segundos, para evitar que la conexión expire.
Sobre la desconexión, es necesario incluir en la aplicación métodos para realizar la
desconexión de forma procedimentada. En el caso de la herramienta desarrollada en el
presente trabajo, se han definido unos límites en tiempo de descarga y número máximo de
tweets, para proceder a la desconexión natural de la API. En este sentido, Twitter procederá
al cierre de una conexión si detecta alguna de las siguientes circunstancias:
• La aplicación establece más de una conexión usando las mismas credenciales
(tokens parametrizados en el protocolo OAuth). En este caso, Twitter cerrará la más
antigua.
• La aplicación detiene la lectura de datos de forma repentina.
30
• La aplicación consume los datos de forma lenta. Cada conexión almacena los datos
en una cola para ser enviados al cliente. Si una aplicación los consume con lentitud,
la cola crecerá, por lo que Twitter cerrará la conexión para evitar problemas de
congestión en sus colas.
• Reinicio de un servidor de streaming.
• Cambios en la configuración de red de Twitter.
En caso de detectarse una desconexión no solicitada, la API permite a la aplicación
el reintento de la conexión, y en caso de fallo en la reconexión, es necesario espaciar en
el tiempo los reintentos de conexión. En caso contrario, Twitter restringirá las conexiones
durante unos minutos, y la API servirá respuestas HTTP 420 (tasa de peticiones limitada).
Cuando una aplicación excede la tasa de peticiones con frecuencia, Twitter puede
bloquear, por un tiempo indeterminado, la IP desde la que se realiza la conexión a la API.
En el apartado 5.1.5 Respuestas API standard se recogen, para su consulta, los códigos
de error HTTP devueltos por la API.
Streaming API proporciona tweets procedentes de los streams en tiempo real de
Twitter, accesibles desde los endpoints predefinidos para cada API. Existen tres tipos
streams básicos a los que conectarse en función del tipo de información que contienen:
• Public streams: Proporcionan acceso al flujo de información pública en Twitter. Son
apropiados para el seguimiento de usuarios específicos, hastags, y recuperación
de tweets para labores de minería de datos.
• User streams: Proporcionan acceso a la información relativa a usuarios de forma
individual. Este stream será reemplazado con el tiempo por un nuevo stream
denominado Account Activity API.
• streams de sitios: Puede considerarse como una extensión de los streams de
usuario, en la que se permite recuperar información de un conjunto específico de
usuarios. Este stream, al igual que el de usuarios, será reemplazado con el tiempo
por un nuevo stream denominado Account Activity API.
31
Para el acceso a los tweets generados por cualquier usuario en tiempo real, como
es el caso de la herramienta desarrollada en este trabajo, la aplicación deberá conectarse
a streams públicos.
Streaming API no recupera retweets o tweets realizados por el ID de usuario que
realiza la petición de búsqueda, aunque puede buscar nuevos tweets o cualquier otro tweet
que mencione dentro de sí mismo a dicho ID de usuario.
Sobre los límites de tasa, establece, como límite de descarga, el 1% del total de
tweets que están siendo tweeteados en el momento de la búsqueda.
Streaming API define los siguientes endpoints públicos para el acceso los streams
públicos:
• POST status/filter: Recupera tweets que coinciden con criterios de búsqueda
definidos.
• GET statuses/simple: Recupera una pequeña muestra aleatoria de tweets.
De los endpoints definidos, el indicado para la búsqueda de tweets es POST
status/filter. Este endpoint está definido por los siguientes valores [27].
• URL de recurso: https://stream.twitter.com/1.1/statuses/filter.json
• Información de recurso: Respuesta en formato JSON, requiere autenticación y
establece un límite de recuperación de tweets de 1% del total
• Parámetros: Parámetros para el acceso al recurso:
� follow: Parámetro opcional que contiene una lista de IDs de usuarios,
separados por comas, indicando los usuarios de los que se recuperarán los
tweets.
� track: Parámetro opcional. Se trata de listado de palabras o frases,
separadas por comas, que permite definir una búsqueda por hastags y/o
términos.
32
� locations: Parámetro opcional. Se trata de un listado, separado por comas,
de pares longitud-latitud que permite definir una búsqueda en función de la
geolocalización de los tweets. Son necesarios dos pares de longitud-latitud
para establecer un área cuadrada en la que el primer par representa la
esquina sudoeste de dicha área. Este parámetro puede ocasionar
problemas, ya que no todos los tweets tienen por qué incluir información de
geolocalización y además el uso combinado de este parámetro con
cualquier otro no filtra todos los resultados por su localización, ya que se
recuperarán tweets que cumplan alguno de los dos criterios. Su uso será
totalmente efectivo si se emplea de forma aislada. Por otra parte, este
parámetro no afecta los tweets que son retweeteados, ya que estos por
definición no contiene información de geolocalización.
� delimited: Parámetro opcional que indica si los mensajes deberían estar
limitados en longitud de bytes, para que algunas aplicaciones puedan saber
cuántos bytes tienen que leer antes del final del tweet. Este factor depende
de la librería cliente que se use para conectarse a la API.
� stall_warnings: Parámetro opcional que indica si se quiere recibir mensajes
de aviso en el caso en que, por alguna causa, Twitter envíe mensajes de
aviso y se esté en peligro de desconexión.
En el caso del presente trabajo, de todos los parámetros disponibles, los que se
han considerado determinantes a la hora de filtrar información son los siguientes: track,
locations, language y stall_warnings.
5.1.5 Respuestas API standard
Los métodos incluidos en las APIs standard de Twitter acceden a la información de
Twitter mediante peticiones HTTP, por lo que todas las respuestas obtenidas en la
ejecución de los métodos propios de cada API llevan asociados, además del objeto JSON
de información, el correspondiente código de estado HTTP [28].
En el caso en que la respuesta sea un error, las APIs devuelven un mensaje JSON
de error, que incluye una descripción y un código de error. Por ejemplo:
{"errors":[{"message":" Rate limit exceeded","code":88}]}
33
Los códigos de respuesta contemplados por las APIs standard pueden consultarse
en el presente documento, en el anexo 10.1 Mensajes de error devueltos por API standard.
En el caso de Streaming API, el significado de los errores asociados a algunos
códigos de estado HTTP enviados por la API en caso de desconexión no solicitada, pueden
consultarse en el presente documento, en el anexo 10.2 Códigos de error HTTP asociados
a Streaming API.
5.1.6 GNIP
Aparte de las APIs ofrecidas, Twitter cuenta con GNIP, empresa fundada en 2008
para la provisión de datos procedentes de APIs relacionadas con redes sociales, y
comprada por Twitter en 2014. Actualmente está orientada a proporcionar soluciones API
para la gestión del 100% (firehose) o del 10% (decahose) de los datos generados en Twitter
[29].
Entre las APIs que ofrece la plataforma se encuentra la API Full Archive Search,
que contiene funciones y métodos para acceder a todo el archivo de datos de Twitter,
permitiendo recuperar información de Tweets tanto en tiempo real como del histórico de
Twitter (hasta del año 2006 como máximo).
Sin embargo, todas estas APIs son de uso comercial, por lo que su uso no es
gratuito.
5.1.7 Evolución APIs de Twitter
Los cambios iniciales indicados por Twitter en el comunicado sobre la unificación
de su plataforma API, recogido en el punto 5.1.1 Impacto de cambios previstos en Twitter,
incluirán, entre otros muchos aspectos, una reestructuración para reducir a tres los tipos
básicos de APIs:
• API para filtrar datos procedentes de los streams de tiempo real.
• API para realizar búsquedas en el archivo de datos de Twitter.
• API para obtener las actividades en tiempo real relacionadas con una cuenta
(incluyendo tweets, mensajes directos, likes y seguimientos).
34
Se otorgarán distintos niveles de acceso a la información obtenida de las APIs, en
función del ámbito y la finalidad de las aplicaciones que hagan uso de ellas, pudiendo haber
un nivel de acceso libre más limitado, un nivel de pago self-service que de acceso a mejoras
en las funcionalidades y límites de las tasas de acceso y recuperación de información, y un
nivel de acceso empresarial que ofrezca sin restricciones toda la funcionalidad de las APIs
[30].
5.1.8 Búsqueda Avanzada de Twitter
Twitter dispone de una herramienta web denominada Búsqueda Avanzada de
Twitter (en adelante BAT), que permite realizar la búsqueda de tweets estableciendo, entre
otros, filtros de fecha para recuperar información en cualquier ventana temporal a partir del
2006, incluyendo tweets generados en tiempo real [31]:
Figura 6: Búsqueda Avanzada de Twitter
Fuente: Búsqueda Avanzada de Twitter [30]
Una de las alternativas a tener en cuenta en el desarrollo de este trabajo, podría
ser el uso de técnicas de Web Scraping para simular, de forma automatizada, el uso de
esta herramienta, y recuperar los tweets a través de la información incrustada
dinámicamente en los objetos del árbol DOM de la propia página generada por la
herramienta [32].
35
Aunque el timeline de los tweets recuperados por BAT abarca toda la ventada
temporal disponible en Twitter (desde 2006 hasta los creados recientemente), la
herramienta ofrece una muestra más o menos amplia de los tweets más importantes que
cumplen con los requisitos de búsqueda, pero no su totalidad, al igual que la REST API.
En el caso de realizar búsquedas de los últimos tweets en tiempo real, sólo se recuperarán
los más importantes.
5.1.8.1 Filtros de búsqueda
BAT ofrece distintos tipos de filtros agrupándolos por su funcionalidad en las
siguientes categorías:
1. Palabras: Permite establece opciones para filtrar:
� Una o varias palabras que deben aparecer de forma obligatoria.
� Una o varias palabras que deben aparecer en el mismo orden con el que se
filtran.
� Una o varias palabras sin tener en cuenta el orden en el que aparecen.
� Una o varias palabras que no deben aparecer.
� Nombres de hastags.
� Idiomas de los tweets.
2. Personas: Permite establecer opciones para filtrar:
� Nombres de cuentas de usuarios origen de tweets.
� Nombres de cuentas de usuarios destinatarios de tweets.
� Nombres de cuentas mencionados en tweets.
3. Lugares: Permite establecer opciones para por la geolocalización actual del
dispositivo desde el que se realiza la búsqueda. No permite indicar cualquier otra
geolocalización.
4. Fechas: Permite establecer opciones para filtrar tweets generados entre una fecha
inicial y una fecha final.
5.1.8.2 Información ofrecida
36
Al realizar una búsqueda, la herramienta ofrece los tweets recuperados organizados
en diferentes vistas:
• Destacados: muestra usuarios y tweets destacados.
• Más reciente: muestra tweets recientes.
• Personas: muestra usuarios.
• Fotos: muestra sólo tweets que incluyen imágenes.
• Videos: muestra sólo tweets que incluyen videos.
• Noticias: muestra tweets categorizados como noticias (contienen enlaces a
artículos en sitios web).
• Transmisiones: muestra tweets de streaming emitidos desde la herramienta
Periscope.
Un ejemplo de resultados obtenidos de una búsqueda puede observarse en la
Figura 7.
Figura 7: Ejemplo de búsqueda en Búsqueda Avanzada de Twitter
Fuente: Búsqueda Avanzada de Twitter [30]
5.1.8.3 Web Scraping
Web scraping es una técnica o conjunto de técnicas que permiten extraer
información de una página web de forma automatizada, simulando si es necesario el
comportamiento humano durante la navegación (relleno de campos, selección de
opciones, etc.) [32].
37
Existen diversas herramientas que de forma genérica realizan esta labor (servicios
online, extensiones de navegadores para realizar scraping, etc.), cuyo éxito está
condicionado, entre otras cosas, a la correcta estructuración del sitio web.
Otra opción, más apropiada para nuestro caso, es generar un algoritmo
personalizado, lo que añade una mayor flexibilidad e integración al proceso. En el caso de
BAT, hay que tener en cuenta que la información se genera dinámicamente en la propia
página de la herramienta.
Actualmente, los lenguajes de programación ofrecen librerías que incorporan
funcionalidades para parsear el código de un sitio web, lo que permite al desarrollador
centrar su trabajo en la detección y análisis de los elementos del código que proporcionan
la información requerida [33].
5.2 Estrategia a seguir para la extracción de tweet s
El uso de técnicas de scraping implica un mayor riesgo de pérdida de funcionalidad
en caso de modificaciones de la herramienta web. Tanto las APIs como la herramienta web
son susceptibles de ser modificadas y actualizadas por Twitter, como de hecho va a ocurrir
con las APIs de Twitter en un futuro próximo, pero en una nueva versión en las APIs es
más probable que sigan siendo, en su mayor medida, compatibles con las actuales que si
la actualización se produce en BAT, en cuyo caso no tendría por qué estar basada en la
versión actual.
Sin embargo, las limitaciones establecidas por los tipos básicos de API que ofrece
Twitter, y el carácter comercial de su plataforma GNIP, incrementan la complejidad en el
desarrollo de una herramienta de recuperación de tweets que intercale el uso de una API
u otra, en función del espacio temporal sobre que el que se desee recuperar la información
en cada momento, ya que sería necesario implementar por separado las APIs de
comunicación con dichas interfaces.
Por otra parte, la limitación temporal de los tweets recuperados mediante el uso de
la REST API es más restrictiva que la establecida en el buscador avanzado de Twitter, por
lo que se resuelve utilizar, en este caso, la información extraída de BAT mediante técnicas
de web scraping.
38
Para recuperar los tweets generados en tiempo real, BAT sólo extrae los más
importantes, por lo que sería recomendable en este caso usar la Streaming API, que como
máximo recupera un 1% del total de los tweets generados en tiempo real, y sólo se
perderían tweets si los recuperados en la búsqueda superan ese límite.
Resumiendo, para realizar una extracción efectiva, habría que implementar dos
métodos distintos de recuperación en función del uso o no de criterios de fecha a la hora
de realizar una búsqueda:
1. Si no se establecen criterios de fechas, conectarse a los streams públicos de Twitter
mediante la Streaming API.
2. Si se establecen criterios de fechas, usar técnicas de scraping sobre BAT.
En el anexo 10.3 Pasos previos para usar la API de Twitter, incluido en el presente
documento, pueden consultarse los pasos a seguir para obtener las credenciales
necesarias para el acceso a la Streaming API.
5.3 Información de campos para búsqueda y extracció n
A continuación, se analiza la información disponible a partir de los métodos de
extracción seleccionados para obtener un modelo normalizado como base de las opciones
de búsqueda e información extraída a través de la herramienta desarrollada en este trabajo.
5.3.1 Información accesible de un tweet
La fuente de la que se extraerán los tweets dependerá del procedimiento empleado
para su recuperación (Streaming API o web scraping), condicionando la información que
puede ser obtenida de cada tweet.
5.3.1.1 Información accesible desde Streaming API
Los tweets son almacenados en objetos Tweet accesibles desde las APIs de
Twitter. En general, un tweet puede contener los siguientes campos, muchos de ellos no
tienen por qué aparecer siempre [34]:
39
• coordinates: Coordenadas geográficas (longitud, latitud) del tweet.
• created_at: Fecha y hora (en formato UTC) de creación del tweet.
• current_user_retweet: Cuando es un retweet, este parámetro indica el ID del
retweet.
• entities: Contiene las entidades que han sido incluidas en el texto del tweet
(hastags, media, urls, user_mentions).
• favorite_count: Número de likes dados por otros usuarios al tweet.
• favorited: Indica si el usuario sobre el que se recupera el tweet ha marcado el tweet
como like.
• filter level: Parámetro usado para marcar la importancia del tweet a la hora de ser
incluido en los streams, de forma que pueda ser recuperado en búsquedas.
• id: Identificador numérico único del tweet. Por problemas de algunos lenguajes de
programación para representar este parámetro como un número, se recomienda
usar el campo id_srt para indentificar un tweet.
• id_str: Parámetro con formato string que representa al identificador único del tweet
(id).
• in_reply_to_screen_name: Cuando el tweet es replicado, este parámetro contiene
el alias del usuario autor original del tweet.
• in_reply_to_status_id: Cuando el tweet es replicado, este parámetro contiene el ID
numérico (id) del tweet original.
• in_reply_to_status_id_str: Cuando el tweet es replicado, este parámetro contiene el
ID string (id_str) del tweet original.
• in_reply_to_user_id: Cuando el tweet es replicado, este parámetro contiene el ID
del autor del tweet original.
40
• lang: Contiene la etiqueta identificadora del idioma del tweet.
• place: Indica un lugar geográfico al que tweet está asociado, no tiene por qué ser
el lugar desde el que se creó el tweet.
• possibly_sensitive: Cuando el tweet incluye una URL, este campo indica si la URL
ha sido identificada como contenedora de contenido sensible.
• quoted_status_id: Cuando el tweet es una cita de un tweet, el ID numérico del tweet
citado es añadido.
• quoted_status_id_str: Cuando el tweet contiene una cita de un tweet, el ID string
del tweet citado es añadodo.
• quoted_status: Cuando el tweet contiene una cita de otro tweet, se le añade el
objeto Tweet correspondiente al tweet original.
• scopes: Contiene parejas clave:valor para identificar el propósito del tweet. Suele
ser usado por los productos promocionados por Twitter.
• retweet_count: Número de veces el que el tweet ha sido retweeteado.
• retweeted_status: Cuando el tweet es un retweet, contiene la representación (el
objeto Tweet) del tweet original.
• source: Utilidad o aplicación usada para publicar el tweet como un string con
formato HTML.
• text: Texto del tweet.
• truncated: Indica si el texto del tweet ha sido cortado por exceder los 140 caracteres.
• user: Usuario que publicó el tweet.
• withheld_copyright: Indica que el contenido del tweet ha sido bloqueado debido a
una queja por vulnerar la DMCA (ley de derechos de autor en USA).
41
• withheld_in_countries: Contiene una lista de códigos de países en los que el
contenido del tweet ha sido bloqueado debido a peticiones de la DMCA.
• withheld_scope: Indica si el contenido bloqueado es el propio tweet o un usuario.
Con fecha del 30/03/2017, y ya con el análisis finalizado de la información ofrecida
y a extraer, Twitter introdujo cambios en los tweets de respuestas a otros tweets. Estos
cambios afectan a las APIs, ya que introducen algunos campos nuevos más, aparte del ya
existente campo text, que incluye el texto truncado del tweet cuando este excede los 140
caracteres. Aunque en dicho momento publicaron un documento resumen, poco a poco
irán generando la documentación técnica con las nuevas especificaciones. En estos casos,
aunque el texto de los tweets sólo muestre 140 caracteres, el texto al completo se incluirá
en el objeto JSON y se organizará en tres partes: prefijo (con los nombres de los usuarios
a los que responde el tweet), sufijo (con la URL que se adjunta en el tweet), y texto (que
contiene el resto del texto del tweet hasta 140 caracteres, tal y como se observa en la
Figura 8.
Figura 8: Futura estructura de un tweet
Fuente: Upcoming changes to Tweets [35]
42
En el caso de Streaming API, por el momento Twitter ha optado por tratar estos
casos tal y como lo hacía antes, pero estableciendo el existente campo truncated a valor
true, e incluyendo el nuevo campo extended_tweet. Si dicho campo aparece, entonces el
tweet se descompondrá en tres subcampos [35]:
• full_text: Contiene el texto completo del tweet, sin truncar.
• display_text_range: Un array de dos índices que identifican el inicio y el final del
contenido visible del tweet.
• entities/extended_entities: Todas las entidades incluidas en el tweet.
En el desarrollo de la aplicación del presente trabajo, se ha tenido en cuenta esta
circunstancia, y se han introducido los cambios necesarios para recuperar el texto completo
en caso de estar truncado, ya que se ha considerado que almacenar en la base de datos
el texto completo, aportará más información en los posteriores análisis que se realicen de
los corpus generados.
5.3.1.2 Información accesible desde el Búsqueda Avanzada de Twitter
No toda la información accesible desde las APIs de Twitter puede ser obtenida
realizando web scraping de BAT. En este caso, los tweets son recuperados por el buscador,
y parte de su información es añadida dinámicamente a elementos del árbol DOM del
documento html de la página.
Si se realiza una búsqueda cualquiera y se analiza, a través del inspector de código
del navegador, el html generado, puede observarse que los tweets recuperados están
incrustados en elementos <li> de una lista ordenada de elementos, pertenecientes a las
clases css js-stream-item y stream-item stream-item y con la propiedad data-item-
type="tweet" (Figura 9).
Figura 9: Detección de un tweet mediante web scraping
Fuente: Elaboración propia
Estos elementos contienen a su vez a otros elementos, de los que a priori se puede
obtener la siguiente información del contenido de cada tweet:
43
• Determinar si se trata de un retweet, mediante la detección de clase js-retweet-text.
Si dicha clase aparece dentro del tweet, indica que se trata de un retweet (Figura
10).
Figura 10: Detección de retweet mediante web scraping
Fuente: Elaboración propia
• ID de un tweet original: Contenido en la propiedad data-tweet-id de las clases tweet,
js-stream-tweet y js-actionable-tweet (Figura 11).
Figura 11: Detección del ID de un tweet mediante web scraping
Fuente: Elaboración propia
• ID de retweet: Si se trata de un retweet, el ID del retweet se obtiene de la propiedad
data-retweet-id de las clases tweet, js-stream-tweet y js-actionable-tweet (Figura
12).
Figura 12: Detección del ID de un retweet mediante web scraping
Fuente: Elaboración propia
• ID de tweet original dentro de un retweet: Contenido en la propiedad data-item-id
de las clases tweet, js-stream-tweet y js-actionable-tweet (Figura 13).
Figura 13: Detección del ID dentro de retweet mediante web scraping
Fuente: Elaboración propia
• ID del autor:
44
� Si se trata de un tweet original, el ID está contenido en la propiedad data-
user-id, de las clases tweet, js-stream-tweet y js-actionable-tweet (Figura
14).
Figura 14: Detección del ID del autor de un tweet mediante web scraping
Fuente: Elaboración propia
� Si se trata de un retweet, el ID del autor del retweet está contenido en valor
id_str de la propiedad data-reply-to-users-json, de las clases tweet, js-
stream-tweet y js-actionable-tweet (Figura 15).
Figura 15: Detección del ID del autor de un retweet mediante web scraping
Fuente: Elaboración propia
• Nombre del autor:
� Si se trata de un tweet original, el nombre está contenido en la propiedad
data-name, de las clases tweet, js-stream-tweet y js-actionable-tweet
(Figura 16).
Figura 16: Detección del nombre del autor de un tweet mediante web scraping
Fuente: Elaboración propia
� Si se trata de un retweet, el nombre del autor del retweet está contenido en
valor name de la propiedad data-reply-to-users-json, de las clases tweet, js-
stream-tweet y js-actionable-tweet (Figura 17).
45
Figura 17: Detección del nombre del autor de un retweet mediante scraping
Fuente: Elaboración propia
• Alias del autor:
� Si se trata de un tweet original, el alias está contenido en la propiedad data-
screen-name, de las clases tweet, js-stream-tweet y js-actionable-tweet
(Figura 18).
Figura 18: Detección de alias del autor mediante web scraping
Fuente: Elaboración propia
� Si se trata de un retweet, el alias del autor del retweet está contenido en
valor screen_name de la propiedad data-reply-to-users-json, de las clases
tweet, js-stream-tweet y js-actionable-tweet (Figura 19).
Figura 19: Detección del alias del autor de un retweet mediante web scraping
Fuente: Elaboración propia
• Texto del tweet: Contenido en el texto del elemento perteneciente a la clase
TweetTextSize (Figura 20).
Figura 20: Detección del texto de un tweet mediante web scraping
Fuente: Elaboración propia
46
• Idioma del tweet: Contenido en la propiedad lang de la clase TweetTextSize (Figura
21).
Figura 21: Detección del idioma de un tweet mediante web scraping
Fuente: Elaboración propia
• Fecha y hora de creación del tweet: En caso de tratarse de un retweet, la
información de fecha y hora que ofrece BAT es la correspondiente al tweet original.
La información está contenida en la propiedad tittle de la clase tweet-timestamp
(Figura 22).
Figura 22: Detección de fecha de creación de un tweet mediante scraping
Fuente: Elaboración propia
• Número de likes del tweet: En caso de tratarse de un retweet, la información de
número de likes que ofrece BAT es la correspondiente al tweet original, aunque su
acceso difiere en función del tipo de tweet. El número de likes está contenido en el
texto de un elemento span, cuya propiedad id se compone de la cadena “profile-
tweet-action-favorite-count-aria- “, seguida del ID del tweet (Figura 23), que, en el
caso de un tweet original será su propio ID, y, en caso de un retweet, será el ID del
retweet.
Figura 23: Detección del número de likes de un tweet mediante web scraping
Fuente: Elaboración propia
• Número de retweets del tweet: En caso de tratarse de un retweet, la información de
número de retweets que ofrece BAT es la correspondiente al tweet original, aunque
su acceso difiere en función del tipo de tweet. El número de retweets está contenido
en el texto de un elemento span, cuya propiedad id se compone de la cadena
“profile-tweet-action-retweet-count-aria- “, seguida del ID del tweet (Figura 24), que,
47
en el caso de un tweet original será su propio ID, y, en caso de un retweet, será el
ID del retweet.
Figura 24: Detección del número de likes de un tweet mediante web scraping
Fuente: Elaboración propia
• Número de réplicas o respuestas del tweet: Contenido en el texto de un elemento
span, cuya propiedad id se compone de la cadena “profile-tweet-action-reply-count-
aria- “, seguida del ID del tweet (Figura 25).
Figura 25: Detección del nº de respuestas de un tweet mediante web scraping
Fuente: Elaboración propia
• Hastags asociados al tweet: Contenidos en el texto de elementos pertenecientes a
la clase twitter-hashtag (Figura 26).
Figura 26: Detección de los hastags de un tweet mediante web scraping
Fuente: Elaboración propia
• Menciones a otros usuarios: Contenidas en la propiedad data-mentions de las
clases tweet, js-stream-tweet y js-actionable-tweet (Figura 27).
Figura 27: Detección de menciones en un tweet mediante web scraping
Fuente: Elaboración propia
• Cita a otro tweet: Si un tweet contiene una cita a otro tweet, la información del tweet
citado está disponible en los de elementos pertenecientes a la clase QuoteTweet
(Figura 28).
48
Figura 28: Detección de cita a otro tweet en un tweet mediante web scraping
Fuente: Elaboración propia
5.3.2 Campos para filtros de búsqueda
Los campos más significativos que permitirán acotar la búsqueda útil de tweets son
los siguientes:
• Términos: Palabras, separadas por comas, que deben aparecer en el texto de los
tweets.
• Fecha de inicio: Fecha mínima de creación de tweets.
• Fecha de fin: Fecha máxima de creación de tweets.
• Idioma: Idioma en el que están escritos los tweets.
• Localización: Geolocalización de los tweets para aquellos que la tengan informada.
Debido a las limitaciones de información impuestas por el buscador avanzado de
Twitter, esta información sólo podrá ser recuperada en las peticiones a la Streaming
API.
De los campos descritos, será obligatorio informar el campo de términos, sin el cual
las búsquedas no podrían recuperar colecciones de tweets relacionados con un mismo
asunto.
49
Por otra parte, si no se establece una ventana temporal de generación de tweets,
mediante las fechas de inicio y fin, la aplicación realizará una extracción por defecto de los
tweets que se estén generando en el momento de la búsqueda mediante peticiones a la
Streaming API.
5.3.3 Campos a extraer
Teniendo en cuenta la forma de acceder a la información ofrecida por la Streaming
API y por BAT, los campos a extraer deben poder ser recuperados tanto en las peticiones
a la Streaming API como en los obtenidos del web scraping sobre BAT. De ellos, se ha
considerado que los campos que más información pueden aportar sobre opiniones vertidas
en Twitter son los siguientes:
• Tema/Dominio: Realmente no es un filtro de búsqueda, sino el nombre que el
usuario asignará al conjunto de tweets que quiere recuperar.
• ID de tweet en formato string.
• ID de tweet en formato numérico.
• Indicador de si se trata de un retweet.
• Texto del tweet.
• Idioma.
• Autor del tweet (ID, alias y nombre de usuario).
• Fecha de creación del tweet.
• Localización (nombre y coordenadas). Aunque este campo sólo está accesible
desde las peticiones realizadas a la API, no todos los tweets recuperados tienen
por qué incluir esta información dado su carácter opcional, por lo que, en el caso de
tweets recuperados desde el buscador avanzado, se asumirá que estos no
contienen información de geolocalización.
• Número de likes (puede aportar información del impacto de una opinión).
• Número de veces que ha sido retwitteado (puede aportar información del impacto
de una opinión).
• Adicionalmente, y a pesar de no ser un campo de extracción directa, se compondrá
para su recuperación y extracción como campo, la URL de la página de cada tweet,
para que el usuario pueda consultarla.
50
5.4 Estudio de posibles tecnologías para implementa r la herramienta
Una vez definidos los métodos de acceso, la estrategia e información necesarias
para realizar búsquedas, y la información a extraer de los resultados de estas, se aborda
el análisis de tecnologías que faciliten la implementación de la herramienta. Se ha optado
por un formato de aplicación web, acorde con la situación actual del desarrollo de software
[36], y con el propósito de aportar, al autor del presente trabajo, competencias digitales en
materia de desarrollo web, ya que es necesario realizar tareas “full stack” para la correcta
sincronización entre el frontend y el backend de la aplicación.
5.4.1 Arquitectura web
La llegada de la Web 2.0, la proliferación de recursos y herramientas a través de la
web, así como como la variedad de las formas en las que pueden ser accedidos, han
contribuido a un considerable aumento de su demanda en detrimento de aspectos básicos
como la escalabilidad y la capacidad de procesamiento. Este hecho ha obligado a un
replanteamiento del modelo tradicional de la arquitectura cliente-servidor, en el que los
clientes realizan peticiones de contenido estático que son procesadas y servidas por el
servidor a través del protocolo HTTP, hacia un modelo dinámico, en el que las respuestas
del servidor son procesadas y generadas en tiempo de ejecución en función del contenido
de las peticiones HTTP.
Además, esta evolución, unida a la creciente diversificación de los tipos de
información y sus fuentes (Redes Sociales, Internet de las cosas, Smart Cities, Open Data,
etc), y su explotación a través del fenómeno Big Data, han derivado en la aparición de
nuevos retos en la arquitectura web para superar barreras relacionadas con el volumen de
información generado, la rapidez con la que se genera y la rapidez con la que se necesita
que sea procesada.
A tal fin, los modelos de arquitectura web han evolucionado, y aunque hoy día
conviven con modelos anteriores, la reestructuración del sistema ha permitido liberar de la
carga de procesamiento a los servidores mediante la redefinición de protocolos de
comunicación y estándares de definición de contenidos, que permiten la ejecución de
código en el propio cliente para generar dinámicamente una respuesta.
51
En este sentido, existen diversos modelos de arquitectura web que pueden
aplicarse en función de las necesidades de cada caso. A continuación, se presentan
brevemente los más comunes.
5.4.1.1 Modelo de dos capas
El sistema se divide en dos capas básicas: cliente y servidor. Si bien en este modelo
gran parte de la lógica de negocio se ejecuta en el lado del cliente, derivando al lado
servidor el almacenamiento y la gestión de la persistencia de los datos (Figura 29), no hay
una distribución clara del reparto de tareas entre ambas entidades. La principal desventaja
que presenta este modelo es la escalabilidad [37].
Figura 29: Modelo de aquitectura web de 2 capas
Fuente: Implantación de aplicaciones web en entornos internet, intranet y extranet [37]
5.4.1.2 Modelo de tres capas
Modelo en el que el sistema se divide en tres capas básicas según su funcionalidad
(Figura 30), en la que cada capa solo se comunica con la inferior [37]:
• Presentación: Recoge la información introducida por el usuario, realiza envíos de
información a las capas de proceso y datos y, genera y representa la vista del
resultado al usuario.
• Negocio o proceso: Realiza las labores del servidor web, recibiendo los datos de la
capa de presentación, realizando operaciones, gestionando datos con la capa de
datos, y devolviendo los resultados a la capa de presentación.
52
• Datos: Realiza las labores de un servidor de datos, realizando operaciones para
asegurar el mantenimiento y la integridad de los datos.
La principal ventaja de este modelo es que facilita la escalabilidad y, al separar su
funcionalidad en bloques distintos, facilita su mantenimiento.
Figura 30: Modelo de aquitectura web de 3 capas
Fuente: Programación por capas [38]
5.4.1.3 Modelo Vista Controlador
Modelo en el que el sistema se divide en tres componentes según su
responsabilidad [37] (Figura 31):
• Modelo: Se encarga de la gestión de los datos, estableciendo mecanismos de
acceso y actualización de los datos. Realiza envíos de los datos a la vista a través
del controlador.
• Vista: Se encarga de la visualización de la interfaz de usuario. Realiza peticiones
de datos al modelo, a través del controlador, para poder representarlos como salida.
• Controlador: Se encarga de gestionar las comunicaciones entre el modelo y la vista,
ejecutando acciones que desencadenan respuestas de ellos según las necesidades
de cada momento.
53
Figura 31: Modelo Vista Controlador
Fuente: MVC [39]
Las principales ventajas de este modelo son que facilita el mantenimiento y la
reutilización de código, y permite la modificación de cualquiera de las partes sin afectar al
resto. Además, diversas tecnologías de programación han implementado diversos
frameworks para el desarrollo de aplicaciones web bajo este modelo.
Existen variantes de este modelo que han ido apareciendo con el paso del tiempo:
HMVC (MVC jerárquico, MVA (Modelo-Vista-Adaptador), MVP (Modelo-Vista-
Presentador), MVVM (Modelo-Vista-Vista-Modelo), etc.
5.4.2 FrontEnd
Actualmente, las tecnologías más extendidas para el desarrollo del frontend de las
aplicaciones web son básicamente 3:
• HTML5: HTML define la estructura básica de una página web mediante el uso de
etiquetas, utilizadas para definir elementos y sus atributos. En su versión 5 se
incorporan, entre otras cosas, nuevas etiquetas compatibles con la Web Semántica
para estructurar un documento, lo que facilita a los buscadores el análisis e
indexación de la información para mejorar el éxito en las búsquedas, etiquetas
específicas para elementos multimedia, etc. [40].
54
• CSS3: Define el estilo con el que serán renderizados los elementos de un
documento HTML o XML. En su versión 3 se incorporan nuevos elementos para
definir esquinas redondeadas, gradientes, sombras, nuevos layouts, etc. [41].
• JavaScript: Lenguaje de programación interpretado ampliamente utilizado en el
lado cliente, ampliamente extendido también en lado servidor. Sigue la norma
ECMAScript obligada para todos los navegadores. Actualmente es el motor de la
Web 2.0 para desarrollar aplicaciones enriquecidas, en la que además de ejecutar
código para realizar automatismos en la propia página, permite establecer
mecanismos de comunicación asíncrona con el servidor. En detrimento de otros
lenguajes como Java, actualmente es el motor de conocidas aplicaciones en
Internet como Facebook, Google, Twitter, etc. [42].
Por otra parte, existen librerías y frameworks basadas en estas tres, que facilitan y
extienden sus funcionalidades. A continuación, se describen algunas de ellas.
5.4.2.1 JQuery y JQuery UI
Se trata de librerías JavaScript de código abierto que permiten la manipulación de
los elementos del árbol DOM de un documento HTML, así como de sus selectores de
diseño CSS para manejar eventos, animaciones, comunicaciones con un servidor usando
AJAX. Ejemplos de uso: Google, Microsoft, IBM, Netflix. JQuery UI es una biblioteca que
contiene interacciones y componentes (widgets, efectos, themes, etc) para enriquecer las
interfaces web creadas con JQuery [43].
5.4.2.2 AngulaJS
Framework JavaScript de código abierto mantenido por Google que implementa el
modelo MVC en su variante MVVM, lo que permite separar la lógica de la aplicación en
capas independientes. Además, amplía la semántica de HTML, proporcionando métodos
para la creación de nuevas etiquetas, y permite la sincronización bidireccional de la
información entre la vista y el modelo. Está recomendado para el desarrollo de aplicaciones
web complejas en las que el uso de JavaScript es determinante para su funcionamiento,
así como en aplicaciones de una sola página (SPA: Single Page Aplication) [44].
55
5.4.2.3 BackBone.js
Librería JavaScript orientada al desarrollo de aplicaciones con marcada interacción
con el cliente que implementa el modelo MVC. Facilita la modularidad entre las capas y
permite la sincronización de la información en las distintas partes de la aplicación e
implementa la arquitectura REST usando JSON como formato principal de intercambio de
información. Está recomendada para el desarrollo de aplicaciones de una sola página
(SPA: Single Page Aplication), simplificando las peticiones AJAX realizadas al servidor,
aunque también es útil para complejas aplicaciones con gran carga de código JavaScript.
Ha sido usada en la construcción de importantes aplicaciones web como Airbnb, BitTorrent,
Linkedln Mobile, etc. [45].
5.4.2.4 Ember.js
Framework JavaScript de código abierto que implementa la variante MVVM del
modelo MVC. Permite la sincronización bidireccional de la información entre la vista y el
modelo, mejorando la escalabilidad en aplicaciones de una sola página. Establece
convenciones en su estructura que permiten generar dinámicamente en memoria los
componentes necesarios en cada momento (vistas, controladores, modelos etc.), sin
necesidad de implementar código para ello. Ha sido usado en aplicaciones web como:
Groupon, Linkedln, Vine, etc. [46].
5.4.2.5 ReactJS
Librería JavaScript de código abierto basada en la arquitectura Flux, siendo ambas
ideadas y mantenidas por Facebook. Está destinada a la optimización de la visualización
en las aplicaciones web. Puede usarse en arquitectutas MVC en las que ReactJS se
correspondería con la vista. Permite agilizar el proceso de renderización mediante la
virtualización del árbol DOM y su uso es compatible con otros frameworks como AngularJS.
Ejemplos de uso: Airbnb, Feedly, etc. [47]
5.4.2.6 Bootstrap
Framework para HTML, CSS y JavaScript creado por Twitter que permite el
desarrollo responsivo de aplicaciones web para adaptar el contenido renderizable al
dispositivo con el que se accede, especialmente si se trata de dispositivos móviles. Puede
56
ser usado conjuntamente con otras librerías y frameworks de desarrollo (JQuery,
AngularJs, etc). [48].
5.4.3 BackEnd
Existen diversas tecnologías de programación para implementar el backend de una
aplicación web, siendo estas independientes de la tecnología empleada en la construcción
del frontend, así como de la implementación de una arquitectura REST para la
comunicación entre cliente y servidor, lo que hace más flexible la elección del lenguaje a
usar en el backend.
La evolución actual del desarrollo de aplicaciones en entonos web no establece el
uso de un lenguaje de programación ideal que proporcione el mejor resultado en todos los
casos, como prueba la heterogeneidad de tecnologías usadas en las aplicaciones web más
importantes, por lo que existe una total libertad para permitir a los desarrolladores la
elección de la tecnología que más se ajuste a sus preferencias. A continuación, se
referencian algunas de las más extendidas.
5.4.3.1 JavaScript – NodeJS
Lenguaje de programación interpretado ampliamente utilizado en el lado cliente y
que empieza a ser empleado en el lado servidor. Sigue la norma ECMAScript obligada para
todos los navegadores [42].
JavaScript es la base del entorno de ejecución NodeJS. Se trata de un entorno de
código abierto que utiliza un modelo de E/S orientado a eventos asíncronos que permite, a
través de sus funciones callbacks, controlar la concurrencia en favor de la escalabilidad, a
diferencia de otros lenguajes en los que la concurrencia se gestiona mediante hilos del
Sistema Operativo. Existen diversos frameworks de NodeJS, por ejemplo: Express,
Sails.js, KOA, Meteor, etc. [49]
5.4.3.2 Java – Spring MVC / Hibernate
Lenguaje de programación multiplataforma orientado a objetos ampliamente
utilizado en aplicaciones web, aunque la tendencia actual lo está enfocando más a la parte
backend. Se trata de un lenguaje fuertemente tipado, y su principal ventaja es la gestión
57
que realiza del uso de la memoria a través de su máquina virtual, y al ser un leguaje
compilado, tiene menos dependencias de otras librerías externas. Su principal desventaja
es que necesita de un intérprete, y es menos eficiente que otros lenguajes [50].
Existen varios frameworks que facilitan el uso de Java, algunos de ellos son:
• Spring MVC: Ofrece servicios para implementar arquitecturas REST, SOAP, etc, y
para favorecer la modularidad y la flexibilidad de la comunicación entre los módulos
[51].
• Hibernate: Basado en ORM (Object-Relational Mapping), facilita el uso de la base
de datos a través de entidades para simplificar el acceso a los datos, aunque no
permite inserciones múltiples y no se recomienda su uso en proyectos pequeños
[52].
5.4.3.3 PHP – Laravel / Symphony
Lenguaje de programación interpretado multiplataforma de código abierto pensado
para el desarrollo del lado servidor en aplicaciones web dinámicas. Permite incluir la
ejecución de código dentro de los propios documentos HTML. No necesita que las variables
sean declaradas, permite la conexión con una amplia variedad de bases de datos, y permite
la programación orientada a objetos. Sitios web como Facebook, Wikipedia o Wordpress
han sido desarrollados con PHP [53].
Los frameworks más extendidos de PHP son:
• Laravel: Framework de código abierto con soporte a la arquitectura MVC, basado
en filosofía ORM para el acceso a la información de la base de datos, con soporte
a caché para agilizar el comportamiento del servidor [54].
• Symphony: Framework de código libre basado en la arquitectuta MVC. Hace uso
de programación orientada a objetos, automatiza aspectos básicos del desarrollo
(uso de AJAX, plugins, etc) y permite el acceso a una gran variedad de bases de
datos mediante el uso de la abstracción ORM. Su principal ventaja es el bajo
consumo de memoria, así como su rapidez, lo que le hace ser recomendado para
el desarrollo de aplicaciones complejas [55].
58
5.4.3.4 Python – Django / Web2py / Pyramid
Lenguaje de programación interpretado, multiplataforma, de código abierto que
permite el uso de tipado dinámico (una misma variable puede tener distintos tipos en sitios
diferentes del código), con una sintaxis bastante intuitiva que requiere menos líneas de
código para realizar tareas básicas. Soporta distintos esquemas de programación:
orientada a objetos, imperativa, funcional. Además, permite la extensión del código en otros
lenguajes de programación como C o C++. Posee una gran variedad de librerías estándar,
entre las que se incluyen facilidades para el desarrollo de aplicaciones web, mapeo de
objetos relacionales mediante la abstracción ORM, web scraping, etc; que hace ser un
lenguaje versátil para ser usado en un gran abanico de situaciones, lo que le está llevando
a convertirse en una de las herramientas más potentes para el desarrollo de aplicaciones.
Algunos sitios desarrollados con Python son Pinterest, The New York Times e Instagram
[56].
Existen muchos frameworks para Python, algunos de los más extendidos para
entornos web son:
• Django: Framework full-stack de código abierto basado en el patrón MVC, aunque
la abstracción en capas que provee permite adaptar el modelo a las necesidades
de cada caso. Facilita el desarrollo rápido de aplicaciones, provee características
adicionales para soportar el cacheo, normalización de URLs, y soporta diversas
bases de datos relacionales nativas. En el caso de bases de datos NoSQL, como
MongoDB, permite su acceso mediante drivers específicos de Python como
PyMongo o bien mediante MongoEngine, que permite el mapeo en bases de datos
de documentos de forma similar al modo de ORM en las bases de datos
relacionales. Además, incluye un servidor web ligero para la fase de pruebas,
aunque para la puesta en producción se recomiendan otros servidores más
especializados [57].
• Web2py: Framework ful-stack de código abierto orientado al desarrollo rápido de
aplicaciones con soporte de base de datos bajo el patrón MVC. Facilita la
escalabilidad, portabilidad a cualquier dispositivo y seguridad. Posee un crontab de
tareas que permite ejecutar procedimientos recurrentes en segundo plano. Para el
acceso a datos implementa una DAL (Data Access Layer) en lugar de ORM,
mapeando las tablas en instancias de la clase Table y los registros en instancias
59
DAL Set, DAL Rows y DAL Fields. Soporta gran variedad de bases de datos
incluyendo MongoDB (NoSQL) aunque en este caso está en fase experimental [58].
• Pyramid: Microframework de código abierto pequeño, rápido y centrado en las
necesidades básicas de las aplicaciones: mapeo de URLs, sistema de plantillas y
aspectos de seguridad. Ofrece una configuración extensible, un core de
funcionalidades personalizable que permite añadir componentes externos [59].
5.4.3.5 Web scraping
Existen numerosas librerías y frameworks destinados a tareas exclusivas de
scraping; siendo bastante amplio el espectro de posibilidades que ofrecen, desde la
recopilación masiva de información de la web para su posterior análisis, hasta su
integración dentro del sector del desarrollo de software en entornos de integración continúa
para la automatización eficiente de pruebas que faciliten una detección ágil de errores [33].
Algunas de estas librerías son dependientes de la tecnología de programación con
la que han sido desarrolladas. De esta forma, pueden encontrarse librerías para Java
(como HtmlUnit), Python (como BeautifulSoup), etc. Por este motivo, se ha optado por
revisar las tecnologías de web scraping una vez que se haya seleccionado una tecnología
de desarrollo concreta para el backend.
5.4.3.6 Base de datos
Para implementar la persistencia de la información recuperada se hace necesario
incluir una BBDD en la que se almacenarán los tweets recuperados.
5.4.3.6.1 Tipos de SGBD
Existen diversos tipos de Sistema de Gestión de Base de Datos (SGBD) atendiendo
al modelo de su estructura. Actualmente los dos tipos de SGBD más extendidos son los
sistemas RDBMS o relacionales y los sistemas NoSQL. Podría comentarse en este punto
diversos aspectos de cada uno de estos sistemas pero, en este caso, los aspectos que
determinarán el uso de uno u otro están relacionados con la naturaleza de la información,
el volumen, sobrecarga de accesos, etc. [60].
60
Entre las características generales de un RDBMS, las más importantes son:
• La naturaleza de los datos es homogénea, almacenándose en tablas según el
modelo entidad-relación.
• Atomicidad de operaciones: Las operaciones o se realizan completamente o no se
realizan. En sistemas con alto volumen de información puede influir en el
rendimiento del sistema.
• Establecen restricciones para mantener la integridad de la información.
• Hacen uso de un lenguaje de consultas estructurado.
• Recomendado para los casos en los que se necesite mantener la fiabilidad y
consistencia en los datos almacenados, así como garantizar la seguridad de las
transacciones.
Entre las características generales de un sistema NoSQL, las más importantes son:
• Permite gestionar de forma flexible datos con estructuras complejas.
• Soporta elevados volúmenes de datos.
• No garantiza completamente la atomicidad de las operaciones ni la consistencia,
sino que en su lugar ofrece la llamada consistencia eventual.
• Prioriza el rendimiento, la escalabilidad y la disponibilidad.
• Recomendado para usos de captura y procesado masivo de datos para su análisis.
En el caso de la herramienta desarrollada en este trabajo, dado el origen masivo de
los datos como es una red social, en este caso Twitter, así como la naturaleza heterogénea
de la información a almacenar (la unidad de información es el tweet, que puede contener
distintos tipos de información), se determina el uso de un sistema NoSQL para gestionar la
persistencia.
61
5.4.3.6.2 SGBD NoSQL: MongoDB
Existen distintos esquemas de SGBD NoSQL que responden a distintos modelos
de almacenamiento de datos. Algunos de ellos son [61]:
• Tipo Clave / Valor: Almacenan claves indexadas asociadas a valores. Ideales para
aquellos casos en los que se necesite almacenar información que pueda ser
recuperada mediante una clave (datos de sesión, perfiles de usuario, preferencias,
etc). Sistemas de este tipo son, por ejemplo, Cassandra, Riak, Redis, etc.
• Documentales: Almacenan datos en forma de documentos, habitualmente con
formato similar a JSON, como es BSON (JSON binario). Permiten realizar
búsquedas avanzadas sobre el contenido de los documentos. Los datos no
necesitan tener un esquema estándar (mismos elementos para cada dato), por lo
que pueden ser usadas en una extensa variedad de aplicaciones de propósito
general, haciendo uso de la arquitectura RESTful para la comunicación cliente-
servidor a través de peticiones HTTP. Sistemas de este tipo son, por ejemplo,
MongoDB, CouchDB, ArangoDB, etc.
• Orientadas a grafos: Almacenan la información en forma de entidades y relaciones
representadas mediante nodos y enlaces respectivamente. Proporcionan una
mayor velocidad en el acceso a la información, haciendo uso de la teoría grafos.
Sistemas de este tipo son, por ejemplo, Neo4j, OrientDB, Virtuoso, etc.
• Columnar (o columna ancha): Almacena los datos en celdas agrupadas en
columnas, que a su vez son agrupadas en familas. Recomendados en aplicaciones
analíticas sobre un volumen masivo de datos, como por ejemplo Data Wharehous,
Business Intelligent, etc. Sistemas de este tipo son, por ejemplo, HBase, BigTable,
etc.
Para el desarrollo de la aplicación del presente trabajo, teniendo en cuenta que el
formato en el que las APIs de Twitter sirven la información es JSON, ampliamente
extendido y recomendado para la transacción de grandes cantidades de información, y que
la comunicación con el servidor se realizará siguiendo una arquitectura RESTful que
simplifica el acceso a recursos mediante el uso de las primitivas de HTTP, se ha optado
por utilizar un tipo de SGBD Documental, siendo MongoDB la elegida debido a que su
creciente expansión ofrece una mayor compatibilidad con las actuales tecnologías de
62
programación, y su uso está recomendado en una gran variedad de ámbitos de aplicación,
sobre todo como soporte de datos en entornos web [62]. Se usará la versión estable 3.2,
ya que la última versión liberada aún está en pruebas.
MongoDB ofrece drivers que permiten gestionar el SGBD directamente desde los
lenguajes de programación, sin necesidad de conocer la sintaxis de sus operaciones
nativas. Los lenguajes de programación soportados son: C, C++, C#, Java, Node.js, Perl,
PHP, Python, Ruby, Scala [63].
5.5 Tecnologías seleccionadas para implementar la h erramienta
En este apartado se determinarán las tecnologías seleccionadas para el desarrollo
de la herramienta propuesta en este trabajo, justificando en cada caso la decisión tomada.
5.5.1 Arquitectura de la herramienta
La heterogeneidad de aplicaciones web y sus distintos ámbitos de uso condicionan
la elección de las distintas soluciones de arquitectura, siendo común en la mayoría de los
casos el uso de un conjunto de ellas.
En el caso de la aplicación objeto del presente proyecto se ha optado por emplear
conjuntamente una arquitectura de tres capas para separar las funcionalidades de la
aplicación, y al mismo tiempo aprovechar las ventajas del modelo MVC implementado por
los frameworks de los distintos lenguajes de programación, que dividen sus funciones entre
el cliente (frontend) y servidor (backend). De esta forma, se conseguirá dotar al sistema de
mayor modularidad, lo que permitirá facilitar las labores de depuración y mantenimiento de
cara a la generación de nuevas versiones correctivas y/o evolutivas de la aplicación, así
como mejorar su escalabilidad.
La comunicación entre los elementos del frontend y el backend se realizará
mediante llamadas AJAX (Asynchronous JavaScript And XML) [64], que permiten
establecer comunicaciones asíncronas en segundo plano entre cliente y servidor, sin
necesidad de cargar de nuevo la página mediante el intercambio de información en un
formato estructurado como XML, o en el caso de esta herramienta, JSON.
63
Por otra parte, para conseguir que estas comunicaciones sean lo más eficaces
posible, se implementará la arquitectura REST (Representational State Transfer) basada
en el protocolo HTTP, que permite identificar los recursos de forma única a través de su
URI (Uniform Resource Identifier), y asociar cada recurso disponible con un formato
específico que se describe por el tipo de contenido pero sin definir un formato específico
de respuesta (normalmente XML y JSON), de manera que pueden ser accedidos mediante
peticiones sin estado, facilitando de esta forma la separación entre cliente y servidor, el
intercambio de grandes cantidades de información con un bajo consumo de recursos, así
como la escalabilidad del sistema [65]. Además, su implementación y el manejo de la
información es más sencillo que mediante el uso de SOAP (Simple Object Access
Protocol).
5.5.2 FrontEnd de la herramienta
Para el desarrollo de la parte frontend, teniendo en cuenta que en este caso la
complejidad de la aplicación se centrará sobre todo en el intercambio de información entre
el servidor y los métodos de acceso a la información de Twitter, se ha optado por hacer
uso de la librería jQuery, más adecuada por su simplicidad en este caso al ser la parte
frontend más liviana en cuanto a los elementos con los que el usuario interactuará con la
aplicación.
Por otra parte, se usará también la librería Bootstrap, que permitirá dotar al sistema
de un comportamiento responsivo para su correcta visualización, independientemente del
dispositivo con el que se acceda a la aplicación.
5.5.3 BackEnd de la herramienta
Para el desarrollo de la parte backend de la aplicación, podría usarse cualquiera de
las tecnologías mencionadas, pero en este caso se ha optado por utilizar el lenguaje Python
y su framework Django, ya que es una tecnología emergente que, por su versatilidad y
potencial, empieza a ser demandada en el entorno profesional para la implementación de
soluciones de prácticamente cualquier índole (comercial, científica, etc). Además, más
específicamente, Python es uno de los lenguajes sobre los que más librerías de soporte se
ofrecen para acceder a las APIs de Twitter; y además, ofrece componentes específicos
para web scraping, que será una de las técnicas que necesitará el presente trabajo para
recuperar los tweets cuando no se establezcan criterios de fechas en las búsquedas.
64
Para realizar el desarrollo con Python, se usará el framework Django, más completo
y extendido, y el que a priori ofrece un mayor soporte para el acceso a bases de datos
NoSQL como MongoDB. Aunque muy recientemente ha sido liberada la versión LTS 1.11,
se utilizará la versión 1.8.7 por ser la versión LTS consolidada más estable, con soporte
hasta abril del 2018.
Para el acceso a la base de datos MongoDB, se optará por usar Pymongo, driver
oficial de Python para MongoDB, a priori más ágil que usar MongoEngine [66].
Para realizar web scraping sobre el buscador avanzado de Twitter, existen varias
librerías basadas en Python ampliamente utilizadas [32], que permiten el desarrollo de
soluciones de scraping adaptadas la estructura de un sitio web en particular:
• BeautifulSoup4: Permite extraer datos de páginas HTML de forma sencilla
realizando un rastreo del árbol DOM. Es especialmente recomendada para trabajar
con HTMLs desestructurados o con una estructura compleja [67].
• Scrapy: Framework completo con arquitectura propia que facilita herramientas para
gestionar el crawling completo. Recomendado sobre todo para aquellos casos en
los que se necesite aplicar scraping a varios sitios [68].
• Selenium Webdriver: librería que simula la navegación desde el propio navegador
para poder acceder a la información del sitio web, lo que hace más complicado para
un sitio web detectar web scraping ya que su comportamiento es aparentemente
humano [69].
Finalmente, se ha optado por utilizar la librería BeautifulSoup4, más sencilla de usar
y, a priori, adecuada para realizar scraping ágil de un solo sitio web. Durante el desarrollo
de la herramienta, como se detallará en el apartado correspondiente al desarrollo, ha sido
necesario revisar y modificar esta decisión en base a los resultados obtenidos.
Para gestionar la comunicación con la Streaming API, Twitter recomienda el uso de
varias librerías para Python. De ellas, las dos más importantes, activamente desarrolladas
y documentadas, son tweepy y twithon. Hay pocas diferencias entre ellas, pero tweepy es
la que se usará en este proyecto ya que incorpora las características más recientes de
Twitter [21].
65
Sobre el servidor HTTP, aunque Django incluye un servidor propio para pruebas,
se usará un servidor Apache 2 para recibir las peticiones del cliente que, aparte de ser el
más extendido por su condición de software libre, puede configurarse independientemente
del sistema operativo sobre el que se instale [70], ofrece una gran escalabilidad y robustez,
y además es recomendado para el uso con Django. Además, será necesario el uso del
módulo mod_wsgi con Apache2, para compatibilizar el servicio desarrollado en Python con
el estándar WSGI (Web Server Gateway Interface) de interfaces entre servidores y
aplicaciones Python [71].
Por último, la persistencia será implementada mediante la base de datos NoSQL
MongoDB, tal y como se ha comentado en el apartado 5.4.3.6.2 SGBD NoSQL: MongoDB
del presente documento.
5.5.4 Sistema Operativo: Ubuntu
Ubuntu es una distribución de Linux que se distribuye bajo licencia de software libre,
por lo que puede ser descargado e instalado sin coste alguno. El software que utiliza
también es gratuito y se caracteriza por ser un sistema operativo abierto, totalmente
configurable y que gestiona los recursos del sistema de forma eficiente. Es de fácil
instalación y dispone de amplio soporte ofrecido por Canonical (empresa responsable del
soporte comercial y servicios relacionados con Ubuntu) y por una amplia comunidad de
usuarios y expertos que están continuamente aportando mejoras y soluciones a los
problemas detectados.
La última versión estable con soporte técnico extendido (LTS) es la 16.04 LTS,
llamada Xenial Xerus, lanzada el 21/04/2016. El desarrollo se realizará sobre la última
release de esta versión, 16.04.2 LTS.
66
6 DESARROLLO
En este apartado se detallarán aspectos relativos al diseño e implementación de la
herramienta de extracción de tweets. Las funcionalidades y flujos detallados se
corresponden con la versión final de la aplicación.
Sin embargo, algunos de los resultados conseguidos en el presente desarrollo no
han sido obtenidos de forma directa a través de hipótesis y diseños iniciales, sino a base
de analizar errores detectados, replantear algunas decisiones tomadas durante el
desarrollo, buscar posibles soluciones, implementarlas y probarlas. Por este motivo, para
comprender mejor el proceso de desarrollo, se ha incluido en este punto un apartado
referente a los problemas detectados durante el desarrollo y su resolución.
6.1 Condiciones de uso de los servicios de Twitter
Antes de comenzar revisando el desarrollo, es importante señalar la postura
adoptada por Twitter ante el uso de técnicas de scraping.
Según se entiende de los términos de servicio publicados por Twitter, tanto a través
de su página oficial [5], como a través de los comentarios de su staff en la comunidad de
desarrolladores [72], está prohibido realizar scraping de cualquiera de los servicios
ofrecidos por Twitter, a menos que exista expreso consentimiento previo por parte de
Twitter (Figura 32).
Figura 32: Térrminos de servicio de Twitter
Fuente: Twitter [5]
67
No obstante, se ha continuado esta línea de investigación y desarrollo ya que ya ha
habido precedentes académicos en esta misma universidad sobre scraping de BAT, y
además, la extracción de la información se circunscribe al ámbito estrictamente académico
del presente proyecto y sin ánimo de lucro.
6.2 Diseño de datos
6.2.1 Modelo Entidad-Relación
Los datos se almacenarán en la base de datos en forma de colecciones (equivalente
a tablas en los SGBD relacionales). Teniendo en cuenta que la información a almacenar
serán tweets, se necesitará la creación de una base de datos, a la que se denominará
tweets, para almacenar todas las colecciones creadas durante las búsquedas. El diagrama
entidad-relación, en este caso, sólo constará de la entidad Tweet, cuyos atributos serán los
campos a extraer, definidos en el apartado 5.3.3 Campos a extraer del presente
documento, siendo id_str su atributo clave (ID de tweet), como puede observarse en la
Figura 33:
68
Figura 33: Modelo Entidad-Relación tweets
Fuente: Elaboración propia
En la Figura 33 se observan dos campos similares: url y tweet_url. Sin embargo, se
trata de dos campos distintos: url se emplea en tareas internas de procesamiento de tweets,
por lo que no se incluirá en la exportación a fichero, y tweet_url es la URL de la página del
tweet.
Por otra parte, dadas las limitaciones de conexión impuestas por la Streaming API
expuestas en el apartado 5.1.4.2 Streaming API, por las que no se permite la conexión
simultánea de aplicaciones con las mismas credenciales, se hace necesario incluir, en el
modelo de datos, una base de datos específica para usuarios, de forma que cada usuario
pueda gestionar sus propias credenciales en el uso de la herramienta. A tal fin, se creará
una base de datos denominada usuarios_rec, que constará de la colección usuarios. El
diagrama entidad-relación, en este caso, sólo constará de la entidad Usuario, cuyos
atributos serán, el id (identificador) y pass (password) del usuario, las claves y tokens de
acceso necesarios para la conexión a la Streaming API, y, además, el atributo gmapkey
para almacenar las credenciales necesarias para acceder a la API de Google Maps,
69
necesaria, como se verá más adelante, para realizar tareas de posicionamiento en el
fronted. Esta entidad, cuyo atributo clave es id (ID de usuario) puede observarse en la
Figura 34:
Figura 34 : Modelo Entidad-Relación usuarios
Fuente: Elaboración propia
6.2.2 Modelo de documentos
MongoDB permite ampliar los tipos usados en JSON con los que proporciona su
formato interno a BSON (Binary JSON) [73]. Los documentos almacenados en la BBDD
tendrán la siguiente estructura, que podría modificarse según las necesidades en cada
momento sin necesidad de realizar una reestructuración en la base de datos:
• Documentos de tipo TWEETS (Figura 35):
70
Figura 35: Modelo de documento tipo TWEETS
Fuente: Elaboración propia
• Documentos de tipo USUARIOS (Figura 36):
Figura 36: Modelo de documento tipo USUARIOS
Fuente: Elaboración propia
6.3 Diseño de la interfaz FrontEnd
Como fase previa al desarrollo de la interfaz del frontend, se han diseñado,
haciendo uso de una versión trial de la herramienta Mockflow para el prototipado de
71
aplicaciones [74], una serie de mockups para cada una de las ventanas, según las opciones
que podría tener la aplicación.
Se trata sólo de prototipos con carácter orientativo, que han derivado en una versión
final con algunos cambios debido a que, durante el desarrollo, ha sido necesario realizar
modificaciones, bien por algunos problemas detectados en algunos componentes, bien por
la inclusión de nuevas opciones como consecuencia de las soluciones adoptadas para
solucionar problemas en el backend, detectados también durante su desarrollo.
A continuación, se describirá brevemente el propósito de cada ventana, si bien, la
visualización y descripción de sus funcionalidades de detallarán en el apartado 10.6 Manual
de usuario del presente documento.
6.3.1 Búsqueda de Tweets
Ventana destinada a la búsqueda de tweets a través de la definición de las opciones
de búsqueda. Además, habilita al usuario para configurar sus credenciales de acceso a la
Streaming API y a la API de Google Maps, necesarias para el uso de la herramienta. De
esta forma el usuario no tendrá que acceder al código fuente para incluirlas.
En las opciones de búsqueda se ha habilitado, para la opción de geolocalización,
un botón para abrir un panel que cargue un mapa para configurar las opciones de
geolocalización (nombre de la localización, latitud y longitud). Dicho panel incluirá un mapa
y permitirá el posicionamiento a partir del nombre o bien a partir de las coordenadas. En
función de las coordenadas del punto seleccionado, se cargará en la ventana principal de
Búsqueda el nombre de la localización, y se almacenarán las coordenadas para enviarlas
en la petición al servidor. Será necesario enviar tanto el nombre de la localización como
sus coordenadas, ya que según se necesite Scraping o Streaming API, se hará uso de una
u otra.
La carga de un mapa el acceso a Google Maps se hará mediante el uso de la librería
gmaps.js en lugar de la librería nativa ofrecida por Goggle, ya que esta es más compleja.
Para el acceso a la API de Google Maps se requiere autenticación, para lo cual es
necesario disponer de una clave de API. Dicha clave se genera a través de Google API
Console, siguiendo las instrucciones especificadas en el propio sitio web del servicio [75].
72
Google ofrece un servicio estándar gratuito y otro Premiun Plan de pago. En este
trabajo se ha hecho uso del servicio gratuito, que incluye 2500 solicitudes gratuitas al día,
calculadas como la suma de las consultas de cliente y servidor, más que suficientes para
el presente proyecto. Si se necesita ampliar dicha cuota es necesario habilitar la facturación
del servicio [76].
6.3.2 Visualización de estadísticas
El propósito de esta ventana es el de visualizar datos y gráficos correspondientes a
estadísticas de las colecciones o dominios almacenados en base de datos. Dichas
estadísticas se ofrecerán de forma global (número total de tweets y número total tweets por
domino) y de forma individual para cada colección existente (número de tweets, número de
tweets por idioma y número de tweets por localización).
6.3.3 Gestión de dominios
Esta ventana permitirá al usuario eliminar las colecciones de tweets pertenecientes
a los dominios que ya no necesite, pudiéndose marcar en una tabla los elegidos para tal
fin.
6.3.4 Exportación
En esta ventana el usuario podrá definir una serie de filtros que le permitan acotar
la información almacenada en la BBDD, seleccionar campos, y exportar la información
resultante en alguno de los formatos disponibles para obtener corpus preparados para ser
tratados por otras herramientas de análisis.
6.3.5 Peticiones AJAX
Para evitar errores de timeout reportados por Apache y controlar el estado de
ejecución de las peticiones en el servidor, en caso de producirse errores que causen una
demora anormal en la ejecución de los procesos, se ha optado por realizar lo siguiente:
1. Configurar en el virtualhost creado en Apache un timeout de 4200000ms (3 horas)
para las peticiones del puerto 8080 (peticiones enviadas a Django), con el fin de
evitar errores de tipo timeout reportados por el propio servidor.
73
2. Configurar en el frontend el timeout adecuado en cada petición ajax en función de
la naturaleza de cada petición. En caso en que ajax devuelva un error por timeout,
se realizará una petición al servidor para gestionar la finalización de la petición
causante del error, evitando de esta forma, posibles fallos en el servidor debidos a
un funcionamiento incorrecto.
Se han definido los siguientes timeouts en función de la funcionalidad ejecutada,
considerándose:
• Configuración, Visualización, Gestión (obtención de dominios) y Exportación
(cálculo de estadísticas): timeout de 30 segundos (30000ms).
• Exportación (exportación a fichero): mismo timeout del servidor Apache, ya que de
antemano no se conoce la cantidad de información a exportar (de media, exporta
9000 registros con todos los campos cada 35 segundos).
• Búsquedas: El tiempo más restrictivo se corresponde a las búsquedas con
Scraping, por lo que el timeout se establecerá de acuerdo a esta restricción
� Búsquedas de hasta 20 minutos: timeout de 50 minutos (3000000ms)
� Búsquedas a partir de 20 minutos: mismo timeout configurado anteriormente
en el servidor Apache.
Si el usuario tiene pensado realizar búsquedas cuyo tiempo de respuesta
(búsqueda + procesado) sea superior a los valores configurados tanto en las peticiones
como en el servidor, deberá ajustar el timeout tanto en el servidor Apache como en las
peticiones ajax al valor deseado para evitar rechazo de las peticiones por timeout.
6.4 Diseño de API BackEnd
Una de las ventajas de usar Django es su versatilidad, permitiendo adaptar el
modelo MVC a las necesidades de cada aplicación. En el caso particular de la aplicación
objeto del presente trabajo, dado que la esta no posee un número elevado de ventanas, se
ha resuelto implementar toda la parte frontend en un solo fichero html, en el que sólo se
visualice la ventana activa en cada momento, de forma que Apache2 sirva directamente el
frontend en estático en la primera conexión, y, posteriormente, canalice las peticiones a
74
Django de forma que este solo sirva la información en crudo, que será cargada
dinámicamente por el frontend. Por tanto, se ha reemplazado del modelo de datos de
Django por el modelo implementado por la propia API desarrollada en este trabajo, y se ha
prescindido de las plantillas de Django encargadas de construir una respuesta html con los
datos obtenidos del modelo, tal y como puede observarse en la Figura 37. Las peticiones
que llegan a Django, son filtradas por su módulo interno URLConf, que, en función de la
URL incluida en la petición, la hace llegar a la vista correspondiente para que esta sea la
encargada de solicitar a la API de extracción el servicio requerido. De esta forma, se
consigue una mayor agilidad en el flujo de trabajo de la herramienta, descargando al
servidor de la tarea de componer una vista a través de sus plantillas en cada petición.
Figura 37: Estructura Herramienta extracción de opniones de Twitter
Fuente: Elaboración propia
Para implementar una arquitectura REST que permita el acceso a cada uno de los
recursos de forma única atendiendo a su URI (Uniform Resource Identifier), se han creado,
aparte de los módulos de configuración propios de Django, varios módulos independientes
que configuran toda una API para extracción de tweets (Figura 36). Estos módulos son los
siguientes:
• api_recotweets.py: Interfaz de entrada a la API, encargada de realizar las llamadas
específicas a las funcionalidades desarrolladas en la API: búsqueda de tweets,
cálculo de estadísticas, eliminación de dominios, exportación de tweets, y gestión
de las credenciales de los usuarios que acceden a la herramienta.
75
• api_twitter.py: Módulo específico para interactuar con la Streaming API de Twitter,
gestionando la conexión, extracción, el formateo de información y la petición de
almacenamiento en base de datos al módulo api_bd.py.
• api_scraping.py: Módulo específico para interactuar con BAT, gestionando la
conexión, la extracción, el formateo de información y la petición de almacenamiento
en base de datos al módulo api_bd.py.
• api_bd.py: Módulo específico para la gestión de la información en la base de datos.
Realiza tareas de creación y eliminación de colecciones, inserción de tweets,
cálculo de estadísticas de la información almacenada en la base de datos,
depuración de tweets dentro del proceso de extracción gestionado por el módulo
api_twitter.py, gestión de la información de credenciales de usuario solicitada por
el módulo api_recotweets.py y exportación a fichero de tweets que incluye:
geolocalización de tweets mediante peticiones a servicio de geolocalización
específico de geocode, y limpieza y conversión, en el texto del tweet, de caracteres
extraños producto de las conversiones entre los formatos UTF8 y ASCII realizadas
durante el procesamiento de la información.
6.4.1 Flujos de búsqueda de tweets
La herramienta implementa dos flujos de búsqueda distintos en función del valor de
los parámetros de fecha:
• Si en la petición de búsqueda no se incluye información de fechas, la API gestionará
la extracción de tweets en tiempo real a través del módulo api_twitter.py, encargado
de realizar peticiones a la Streaming API de Twitter.
• Si en la petición de búsqueda se informa una ventana de fechas, la API gestionará
la extracción de tweets del histórico de Twitter a través del módulo api_scraping.py,
encargado de realizar tareas de web scraping a BAT.
A continuación, se detallan cada uno de estos flujos.
6.4.1.1 Búsqueda de tweets en tiempo real
76
En el caso en que la búsqueda se solicite sin informar las fechas, el flujo de
búsqueda, a través de la Streaming API, realizará las siguientes tareas, tal y como se
observa en la Figura 38:
Figura 38: Diagrama de flujo de búsqueda de tweets en tiempo real
Fuente: Elaboración propia
77
En primer lugar, se obtendrán y formatearán los parámetros de la petición, entre
ellos los referentes a los límites en tiempo y cantidad de tweets que como máximo durará
el proceso de búsqueda. Estos parámetros los informará el usuario desde la interfaz de
búsqueda al realizar la petición.
A continuación, se determinará si la petición incluye o no la condición de búsqueda
por geolocalización. En caso de incluirla se calculará, a partir de las coordenadas de la
posición por la que se realizará la búsqueda, un bounding box con forma cuadrada, de
forma que Twitter devuelva todos los tweets geolocalizados dentro del área definida.
Debido a que Streaming API, al usar las cláusulas de sus filtros de búsqueda, realiza una
operación lógica de “OR” cuando se incluye el filtrado por geolocalización, Twitter aconseja
ejecutar la búsqueda por geolocalización y configurar dicho bounding box como único
parámetro de búsqueda a enviar al listener, y aplicar el resto de filtros en un segundo
filtrado a nivel de base de datos.
Posteriormente, el flujo continuará de la siguiente manera:
1. Crear en base de datos la colección que almacenará los resultados de la búsqueda.
2. Conectar un listener con el stream público de Twitter y autenticar las credenciales
del usuario.
3. Enviar al listener los filtros de búsqueda para que empiece la escucha y descarga
de tweets
4. Se establecerá un disparador que compruebe constantemente si se ha alcanzado
alguno de los límites (tiempo o número de tweets) parametrizados en la búsqueda.
5. Mientras no se alcancen los límites, el módulo va consumiendo los tweets que sirve
la API, obteniendo la información requerida de cada tweet hasta que el disparador
finaliza la búsqueda por alcanzar alguno de los límites.
En caso de incluir filtrado por geolocalización, se realizará un filtrado de los registros
en base de datos simulando el comportamiento de Streaming API al realizar las búsquedas
con respecto a los términos a buscar en el texto de los tweets. Cuando Streaming API
realiza búsquedas por términos, además de en el texto, busca en las URLs incluidas en el
78
texto y en el alias del usuario, entre otros. Por este motivo, la herramienta realizará las
siguientes tareas en la fase 2:
1. Actualizar las URLs a formato normal en los tweets que incluyen URLs en el texto.
Esta conversión es necesaria porque Twitter almacena con formato corto las URLs
incluidas como parte del texto. La conversión se realiza a través de peticiones a un
servicio de conversión, que como se comentará más adelante en el apartado de
problemas, tiene políticas restrictivas de uso al ser un servicio gratuito, lo que en
ocasiones se traduce en errores de conversión que generan problemas.
2. Filtrar tweets de la colección creada eliminando los que no coincidan con los
criterios de búsqueda:
� Si el usuario ha seleccionado el idioma como parámetro en la búsqueda,
primero se eliminan todos los registros que no cumplan este criterio.
� Se buscan en la colección los tweets que no tienen en el texto los términos
de búsqueda (teniendo en cuenta, en caso de haber más de un término, si
el usuario ha seleccionado el modo “todos”, referente a que todos los
términos de búsqueda deben a aparecer en el texto, o el modo “cualquiera”,
referente a que cualquier término pueda aparecer en el texto de búsqueda).
� Los tweets resultantes de la búsqueda, se analizan para determinar si los
términos aparecen en la URL o en el campo alias, y, en caso contrario, se
eliminan.
Al recuperar cada tweet, se determinará si este se trata de un retweet,
descartándose si el usuario ha seleccionado en la búsqueda la opción de no recuperar
retweets.
Durante la lectura de tweets, se obtendrá, si está informada, la información de
geolocalización del tweet. Para ello se buscará en el tweet los campos de coordenadas y,
en caso de no existir, se comprobará si el tweet tiene informado el campo places, en cuyo
caso, se obtendrá la información del nombre de la localización y las coordenadas
asociadas, evitando así realizar una petición al servicio de geolocalización, que, como se
verá en el apartado de problemas, al ser gratuito, tiene una política de peticiones restrictiva.
Las coordenadas aportadas por place vienen informadas en un bounding box que define
79
un área cuadrada, por lo que en ese caso las coordenadas se obtendrán calculando el
punto medio del área definida.
Por cada tweet recuperado, además de la información propia del tweet, se
compondrá la URL de la página del mismo, y se insertará en la base de datos.
En el flujo de tweets que se obtiene de la Streaming API, Twitter incluye mensajes
de aviso y mensajes denominados newline para mantener la conexión activa en el caso en
que, pasados unos segundos, no se detecten tweets en el stream. Entre los mensajes de
aviso, la herramienta diferenciará los que sólo son de aviso, manteniendo la conexión
abierta sin perjuicio de incurrir en una falta considerada grave por Twitter (por ejemplo,
realizar más peticiones de las permitidas), de los mensajes de aviso que sí son
bloqueantes, en cuyo caso se cerrará la conexión de forma normalizada, generando un
aviso por error en la herramienta. La herramienta informará por ventana de los avisos con
códigos de error bloqueantes:
1. Errores por tasa conexiones/peticiones excedido.
2. Errores de autenticación de claves.
3. Errores por timeout de la conexión.
4. Excepciones.
En cualquier caso, todos los avisos y errores quedarán registrados para su consulta
en un fichero de log, cuyo contenido de detallará más adelante.
Finalmente, una vez finalizada la búsqueda, los tweets de la colección resultante se
analizarán para determinar si tienen informados los campos de coordenadas geográficas y
si además no tienen informado el nombre del campo de localización, en cuyo caso se
geolocalizarán a través de peticiones a un servicio de geolocalización.
6.4.1.2 Búsqueda de tweets en una ventana temporal
En el caso en que la búsqueda se solicite para una ventana de fechas determinada,
el flujo de búsqueda, a través de web scraping de BAT, realizará las siguientes que se
comentan a continuación, tal y como se observa en la Figura 39:
80
Figura 39: Diagrama de flujo de búsqueda de tweets en ventana temporal
Fuente: Elaboración propia
81
En primer lugar, se obtendrán y formatearán los parámetros de la petición, entre
ellos los referentes a los límites en tiempo y cantidad de tweets que como máximo durará
el proceso de búsqueda. Estos parámetros los informará el usuario desde la interfaz de
búsqueda al realizar la petición.
A continuación, se construirá, en función de los parámetros informados, la URL que
generaría BAT si se realizara la misma búsqueda desde su interfaz, y se creará en base
de datos la colección que almacenará los resultados de la búsqueda.
Se lenvantará, a través de Selenium, una instancia de su webdriver PhantomJS
para cargar la URL de búsqueda y conectarse a BAT y se establecerá un disparador que
calcule el tiempo de búsqueda transcurrido. El webdriver se ha configurado para simular la
instancia de un navegador Mozilla Firefox, por lo que es requisito indispensable el uso de
la presente herramienta con un navegador Mozilla Firefox.
Teniendo en cuenta que, en BAT, el número de tweets cargados antes de bajar el
scroll es como máximo 20, se calculará, en función del parámetro número máximo de
tweets que el usuario haya indicado en la consulta, el número de veces que como mínimo,
se deberá bajar el scroll para alcanzar el total de tweets deseados.
A continuación, se cargará en local el html actual de la página de BAT y, mediante
el uso de BeautifulSoup4 se parseará y se calculará el número de tweets disponibles.
En el caso en que el usuario haya seleccionado la opción de no admitir retweets,
se calculará el número de retweets.
Se determinará si el número de los tweets detectados (a los que se restará la
cantidad de retweets si el usuario ha seleccionado no admitirnos) ha alcanzado el límite
establecido, en cuyo caso se interrumpe la carga.
Se comprobará si se ha llegado al límite temporal. En caso de ser así, se interrumpe
la carga; y en caso de no ser así, se procederá a simular la bajada de scroll, tantas veces
como el número mínimo calculado con anterioridad, dejando, entre cada bajada, un espacio
temporal de 2 segundos para que el webdriver pueda actualizar el html con los nuevos
tweets, y comprobando si se ha alcanzado el límite temporal para interrumpir la carga.
82
Al llegar al número mínimo de bajadas de scroll, se espera a que el html resultante
se cargue del todo, ya que a medida que crece el número de tweets la carga se ralentiza.
Una vez cargado todo el html, se vuelve a comprobar si se ha llegado al límite temporal,
de no ser así comenzará el proceso de nuevo hasta que alguno de los límites se alcance.
Una vez alcanzado alguno de los límites de búsqueda, se parsea el html resultante
para recalcular el número final de tweets obtenidos, y se almacenan todos los tweets
detectados y se comienza la extracción de la información de cada uno de ellos a través de
la identificación de los elementos html analizados en el apartado 5.3.1.2 Información
accesible desde el Búsqueda Avanzada de Twitter.
Por cada tweet recuperado, además de la información propia del tweet, se
compondrá la URL de la página del mismo, y se insertará en la base de datos.
6.4.2 Comunicaciones Apache2 – Django
La gestión de las peticiones en Apache2 puede dividirse en dos tipos:
1. Gestión del contenido estático: Sirve la interfaz visual de la aplicación web, sin
información.
2. Gestión de peticiones al servidor backend: Sirve la información obtenida por las
funcionalidades desarrolladas en el servidor.
Django ofrece la posibilidad de gestionar ambos tipos de peticiones, si bien se
recomienda gestionar las peticiones de archivos estáticos a través del propio servidor web,
en este caso Apache2, para liberar a Django de esta tarea y mejorar su rendimiento, sobre
todo en aplicaciones de gran volumen.
En el presente trabajo se ha optado por liberar a Django de esta tarea, y permitir
que Apache2 gestione directamente las peticiones sobre el contenido estático. Para ello,
se configurado en Apache2 (/etc/apache2/sites-available) un host virtual (recotweets.conf)
con dos puertos para distinguir dos tipos de peticiones [77]:
• Peticiones al puerto 80: Sirven el frontend estático.
83
• Peticiones al puerto 8080: Sirven las peticiones al servidor Django para ejecutar las
correspondientes funcionalidades del servidor.
Para evitar problemas relacionados con la política same-origin en peticiones cross-
domain [78], es necesario configurar, en el fichero de virtual host, los dos servicios con el
mismo ServerName (recotweets.com) y añadir el dominio recotweets.com al listado
ALLOWED_HOSTS de settings.py en Django.
Dado que durante el desarrollo servidor y cliente están alojados en la misma
máquina, y que el desarrollador no posee un dominio de su propiedad, para realizar en
local una simulación más realista se ha modificado el fichero /etc/hosts de la máquina para
añadir un dominio y la IP local que es la dirección del servidor:
/etc/hosts: 192.168.0.192 recotweets.com
6.4.3 Explicación práctica del volumen ofrecido por Streaming API
Streaming API ofrece el 1% del total de tweets en cada búsqueda. Una búsqueda
con más términos podría suponer un volumen superior al 1% ofrecido por la API. Una vez
comenzada la descarga, cuando la API finaliza el cálculo del volumen potencial al que se
tendría acceso con los filtros utilizados, si este cálculo supera el 1%, envía un aviso de
superación de límite, momento en el que se recomienda finalizar la conexión para evitar
posibles bloqueos por parte de Twitter.
Si se emplean muchos términos en la búsqueda, la probabilidad de alcanzar el límite
del 1% será mayor, por lo que podrían dejar de recuperarse muchos tweets que sí podrían
ser recuperados si la búsqueda se realiza con menos términos o incluso si se realiza una
búsqueda independiente por cada término. Para evitar una saturación de conexiones,
Streaming API sólo permite un máximo de 2 conexiones por aplicación. Por lo que
correspondería al propio usuario decidir si hacer una única búsqueda con más términos o
realizar varias búsquedas con un número reducido de términos.
Para ilustrar este comportamiento, se ha realizado una búsqueda con varios
términos, y a continuación se ha realizado una búsqueda por cada término independiente.
En el primer caso, se ha obtenido un aviso de Twitter porque el volumen de tweets a los
que se tendría acceso supera el 1%, y sólo se han podido recuperar 56 tweets. En el caso
84
de los términos independientes, la suma de tweets obtenida ha sido de 4768. Estos son los
datos reales:
• Búsqueda con varios términos: 56. Filtros empleados:
� Términos: cristiano, messi, corrupción, feliz, happy, viernes, party, ciudad
� Modo: cualquier término
� Idioma: cualquier idioma
� Localización: No
� Places: Si
� Retweets: Si
• Búsquedas con las mismas opciones, pero términos independientes: 4768
� cristiano = 240
� messi = 1007
� corrupción = 70
� feliz = 1107
� happy = 67 (Límite alcanzado, lo que quiere decir que más del 1% de los
tweets que en ese momento se estaban generando, incluían la palabra
happy)
� viernes = 145
� party = 1915
� ciudad = 217
6.4.4 Sistema de logs
Adicionalmente a los módulos que componen la API de la herramienta desarrollada,
se ha desarrollado un módulo de log (log.py) que permite registrar toda la actividad del
backend, clasificando las trazas almacenadas en INFO (informativas), WRN (warnings) y
ERR (errores), y creando archivos de logs que se autohistorifican al llegar a un tamaño
determinado.
Esta utilidad facilita la detección de errores, aportando en muchos casos,
información del fichero fuente y número de línea en las que se localiza el error, así como
la causa y mensaje del error recibido (Figura 40).
85
Figura 40: Ejemplo de traza de error
Fuente: Elaboración propia
La ejecución de las peticiones realizadas al servidor comienza y finaliza con la
palabra BACKEND (Figura 41), y al finalizar incluyen información del tiempo empleado en
ejecutar una petición (Figura 42).
Figura 41: Ejemplo de traza de inicio de petición
Fuente: Elaboración propia
Figura 42: Ejemplo de traza con cálculo tiempo total empleado
Fuente: Elaboración propia
Los logs tienen como formato de nombre LOG_YYYY-MM-DD.log, y se almacenan
en la ruta:
/home/proyecto_tfg/proyecto_django/recotweets/log
6.4.5 Cifrado SSL
Para proteger el envío de las claves de acceso a Twitter y a la API de Google Maps
se ha configurado Apache2 para el cifrado de la comunicación mediante SSL. Para ello es
necesaria la generación un certificado firmado por una Entidad Certificadora Autorizada,
no siendo gratuita esta generación. Sin embargo, para entornos de desarrollo o para un
uso interno es posible generar un certificado SSL autofirmado.
86
En este trabajo, se han seguido los siguientes pasos para habilitar el cifrado de las
comunicaciones:
1. Generar certificado SSL con autofirma. Para ello, consultar el anexo 10.4
Generación de certificado SSL con autofirma, incluido en el presente documento.
2. En el fichero de virtual host de Apache2 configurado para las comunicaciones
Apache – Dango de esta herramienta, añadir las siguientes directivas a cada virtual
host existente:
SSLProxyEngine on
SSLEngine on
SSLCertificateKeyFile /etc/ssl/certs/ssl.key
SSLCertificateFile /etc/ssl/certs/ssl.crt
3. Añadir un nuevo virtual host para redireccionar las peticiones no SSL del puerto 80.
<VirtualHost *:80>
ServerName recotweets.com
Redirect permanent / https://recotweets.com/
</VirtualHost>
Al cargar por primera vez la aplicación con el navegador aparecerá un error
relacionado con la seguridad, por lo que es necesario añadir una excepción de seguridad
para que el certificado sea reconocido como seguro. Este proceso es necesario hacerlo
para:
https://recotweets.com:80
y para
https://recotweets:8080
(en este caso acceder a
https://recotweets:8080/index.html/configuracion
87
para que el navegador muestre la ventana de excepción y poder añadir el
certificado).
6.5 Problemas y Soluciones
Durante la fase de desarrollo han ido surgiendo algunos problemas que han
obligado a replantear algunas hipótesis iniciales para poder solucionarlos. A continuación,
se comentan los más importantes, así como las conclusiones y soluciones a las que se ha
llegado para superarlos para obtener la versión final del software, descrita a lo largo del
presente documento.
6.5.1 BackEnd
6.5.1.1 Streaming API
Analizando las posibilidades que la API ofrece, se ha decidido incluir la
geolocalización de tweets al considerar como valor añadido para la herramienta poder
ofrecer información sobre la localización en la que se han generado los tweets.
La concatenación de filtros en Streaming API se comporta como OR y no como
AND cuando se incluye la localización. Si se quiere simular un filtro único que incluya
localización con AND en sus cláusulas, primero hay que realizar el filtrado con la
localización y posteriormente filtrar en BBDD con el resto de cláusulas. Este
replanteamiento ha generado los siguientes problemas:
6.5.1.1.1 Búsqueda por localización
Al filtrar directamente por los términos, Streaming API comprueba que estos no
estén contenidos en la URL que a veces los usuarios incluyen en los tweets como enlaces
a otras páginas o tweets. Al realizar una búsqueda por geolocalización, los filtros de
términos y de idioma (los de fechas se aplican en la parte de scraping) deben aplicarse
sobre los resultados obtenidos en la base de datos en una segunda fase. Los tweets
contienen el campo expanded_url dentro del objeto entities, que usualmente puede
contener la URL extendida de la URL incluida en los tweets. Sin embargo, durante las
pruebas se ha detectado que, en algunos casos, Streming API está informando el campo
88
expanded_url no con la URL extendida incluida en el tweet, sino con la URL extendida de
la página del propio tweet. Por ejemplo:
En el tweet extraído y ya formateado (los caracteres raros son debidos a la
representación unicode del diccionario, pero son correctos) de la Figura 43:
Figura 43: Problemas búsqueda por localizacion (I)
Fuente: Elaboración propia
el texto:
"Papeticos @PPopular cuantos años lleva muerto #MiguelAngelBlanco xq no fue
#Gallardon el q puso la placa. Criticáis lo q no hacen los demas https://t.co/c59QHG5zHJ"
incluye la URL: https://t.co/c59QHG5zHJ, cuya versión extendida es:
https://twitter.com/PPopular/status/884721288945823744
Y la URL incluida en expanded_url es la observada en la Figura 44:
Figura 44: Problemas búsqueda por localizacion (II)
Fuente: Elaboración propia
https://twitter.com/i/web/status/885786636029755392
que hace referencia a la URL de la página del propio tweet:
https://twitter.com/OskyGrumpy/status/885786636029755392
La solución a este problema es descartar el uso del campo expanded_url, detectar
la URL incluida en el texto del tweet y realizar la conversión a su URL extendida. Esta
conversión se realiza a través de peticiones a un servidor de conversión, mediante el uso
89
de la librería requests. Existe un problema asociado al tiempo invertido en realizar
peticiones y recibir respuesta que se ha solucionado empleando hilos de ejecución
simultánea, minimizando así el impacto en el tiempo total de procesado de todos los tweets.
Sin embargo, la ejecución simultánea de hilos puede causar en ocasiones problemas
debido a la saturación de peticiones. Estos problemas son:
• Errores reportados por el servidor al detectar varias indirecciones en la URL
solicitada (Figura 45). Por defecto, hay un límite de 30 indirecciones permitidas [79],
cuando este límite se supera se produce una excepción ya que podría tratarse de
un redireccionamiento circular. Este comportamiento es frecuente en URLs usadas
para publicitar algo.
Figura 45: Problemas búsqueda por localizacion (III)
Fuente: Elaboración propia
• Errores por timeout del servicio (Figura 46): se producen cuando el servidor no ha
emitido una respuesta después del tiempo definido para timeout (en segundos). Se
recomienda, para entornos productivos, usar el parámetro timeout en las peticiones
al servidor y capturar la excepción en caso de producirse.
Figura 46: Problemas búsqueda por localizacion (IV)
Fuente: Elaboración propia
Después de varias pruebas se ha conseguido minimizar estos problemas limitando
el número de hilos simultáneos, configurado un timeout en la llamada de 2s y capturando
la excepción para que, en caso de producirse, se marque el registro para un segundo
reintento y se continúe con la ejecución. Además, cuando se detecte una excepción por
exceso de indirecciones en la URL, no se extraerá y se continuará con la ejecución.
6.5.1.1.2 Geolocalización de tweets extraídos
90
La localización de cada tweet a partir de sus coordenadas extraídas se realiza a
través del paquete geocoders de la librería Geopy, que permite realizar peticiones de
localización a un servidor de geocode. Los problemas detectados se comentan a
continuación.
Cuando se recuperan tweets con información de geolocalización (sobre todo en las
búsquedas por geolocalización, en las que todos los tweets deben estar geolocalizados),
debido al tiempo empleado en cada petición/recepción de geolocalización, se reciben, a
través de Tweepy (Figura 47), mensajes de alerta de Twitter sobre ralentización en el
procesado de tweets realizado por la aplicación, lo que ocasiona el rechazo de los tweets
que se reciben del stream al no poder ser consumidos.
Figura 47: Problemas geolocalización de tweets extraídos (I)
Fuente: Elaboración propia
Se ha comprobado que el principal factor de ralentización es la detección de la
información de posicionamiento y las peticiones realizadas al servidor de geolocalización
antes de almacenar cada tweet en la base de datos. Se ha realizado una prueba de
ejecución de 20 minutos sin calcular geolocalización y ha funcionado correctamente.
Se han analizado algunas posibles soluciones:
• Usar hilos para descargar los tweets. Se ha probado a implementar esta solución y
el procesado ya no ralentiza la recuperación de tweets, pero al generar muchas
peticiones simultáneas, se ha producido un nuevo problema por saturación del
servidor de geolocalización y bloqueo temporal de peticiones al servidor (Figura 48).
El uso de geocode, al ser gratuito, tiene una política de uso de 1 petición / segundo
[80]. Es posible que, si se superan este límite, se bloqueen temporalmente las
peticiones realizadas al servidor (Figura 49). Existe un servicio de pago en el que
se amplían los límites establecidos en dicha política.
Figura 48 Problemas geolocalización de tweets extraídos (II)
Fuente: Elaboración propia
91
Figura 49 Problemas geolocalización de tweets extraídos (III)
Fuente: Elaboración propia
Por otra parte, usar hilos en el hilo principal del listener supone un riesgo en el
control de hilos y en la memoria que estos puedan consumir, si su número se incrementa
considerablemente como consecuencia de una descarga masiva de tweets.
• En lugar de extraer la información y almacenarla ya formateada en tiempo real,
almacenar cada tweet directamente en base de datos y después extraer la
información. Esto supondría un nivel extra de procesamiento en base de datos a
los ya implementados.
• Al extraer la información directamente de cada tweet recuperado, emplazar la
geolocalización en otra parte del código fuera del flujo del listener (por ejemplo, al
obtener las URLs extendidas) para que este no se vea afectado.
• Existen otras alternativas para geolocalizar a parte de Geopy, pero todas tienen
igualmente restricciones y Geopy parece ser la más accesible y menos restrictiva
[81].
Finalmente, y después de varias pruebas e implementaciones se ha conseguido
solucionar el problema almacenando la localización en un subdiccionario que contenga los
campos de nombre y coord[longitud, latitud], y calculando la geolocalización sin el uso de
hilos simultáneos (lo que excluye la posibilidad de realizar las peticiones al calcular URLs
extendidas) y fuera de la lectura del listener. Las restricciones impuestas por el uso de un
servicio gratuito de geolocalización obligan, en este caso, a situar la generación de
peticiones en la parte del código donde el número de tweets esté totalmente depurado y
antes de calcular las estadísticas por dominio, y de la exportación a un fichero; es decir,
justo después de realizar el filtrado de 2º nivel, aunque para ello sea necesario volver a
recorrer la colección completa.
92
En la selección de campos incluida en la ventana de Exportación del frontend, se
sustituirá el nombre de "Localización" por "Localización +", ya que, al igual que "Autor+", el
campo contiene tres subcampos más, por lo que desmarcar este campo supondrá la
selección de todos los subcampos relacionados.
Por otra parte, el filtro de geolocalización ofrecido por Streaming API realiza la
búsqueda a través de dos campos:
• coordinates: definido por los valores de longitud y latitud. Para realizar la búsqueda
en el filtro es necesario establecer un bounding box (área con forma poligonal,
usualmente un cuadrado) pare definir el área dentro de la cual deberán estar
localizados los tweets a buscar.
• place: nombre de una localización con unas coordenadas establecidas. Este campo
puede ser informado para asociar una localización en la creación de un tweet, pero
no necesariamente indica que el tweet haya sido creado en dicha localización.
Durante el proceso de búsqueda, Streaming API comprueba si el campo
coordinates está informado en los tweets, en caso de no ser así, comprueba la existencia
del campo places y si las coordenadas informadas en dicho campo quedan dentro del
bounding box establecido en la búsqueda.
En el caso de este trabajo, al recuperar tweets mediante el filtro location, solo se
estaban almacenando en base de datos los tweets que tienen incluida información
específica de la posición desde la que han sido creados, a través del campo coordinates.
Sin embargo, no son muchos los que se generan. Con el objetivo de recuperar más tweets
geolocalizados y, al mismo tiempo, reducir el número de peticiones realizadas en el
servidor de localización, se ha considerado finalmente añadir a la extracción los tweets que
tengan informado el campo places si coordinates no está informado. Al recuperar places,
si tiene informado su nombre (name), usarlo como geolocalización en lugar de ejecutar el
cálculo a partir de coordenadas.
Dado que la posición incluida en places no tiene por qué ser la posición real desde
la que se ha creado un tweet, se dejará a elección del usuario desde la interfaz del frontend
decidir si incluir en la extracción de geolocalización la opción de recuperar tweets con un
lugar asociado a través de este campo. En todo caso, si un tweet contiene información de
geolocalización, su posición real será informada en los campos latitud y longitud.
93
6.5.1.1.3 Pruebas de estrés
Las extracciones de tweets geolocalizados son las que más recursos y tiempo
consumen, ya que la geolocalización debe ser filtrada por Streamin API en primera
instancia y de forma independiente del resto de filtros, que deben ser aplicados en una
segunda fase a nivel de BBDD, con dos actualizaciones previas:
• URLs detectadas en el texto de los tweets para transformarlas desde el formato
corto a su formato normal o extendido, de forma que también pueda realizarse en
ellas la búsqueda de los términos seleccionados.
• Geolocalización de los tweets a partir de sus coordenadas.
Una vez solucionados los problemas relacionados con estos puntos, se ha probado
la extracción y exportación a fichero de tweets geolocalizados con un límite temporal de 30
minutos, con resultado final satisfactorio. Se han obtenido 15 tweets, invirtiendo un tiempo
total de 0:33:26.072377 en completar el proceso (Figura 50). Si bien el número de tweets
obtenido finalmente es bajo, hay que tener en cuenta que esta extracción se realiza en
tiempo real y a una hora concreta y sobre un área específica. La generación de tweets
geolocalizados es aleatoria, y aunque normalmente no es grande, sería interesante realizar
un estudio de comportamiento de los usuarios en relación a la fluctuación del volumen
tweets a lo largo del día; algo que está fuera del alcance de este proyecto.
94
Figura 50: Pruebas de estrés Streaming API (I)
Fuente: Elaboración propia
Tras la implementación de la parte de scraping y repetición de algunas pruebas de
estrés, se ha detectado que el proceso de depuración para el filtrado de 2º nivel (base de
datos) consume bastante tiempo cuando el volumen de registros a comprobar y depurar
es elevado (Figura 51).
Figura 51: Pruebas de estrés Streaming API (II)
Fuente: Elaboración propia
95
Para agilizar el proceso de depuración se ha introducido el uso de hilos de ejecución
simultánea y la preselección de registros a analizar en el filtrado:
1. Si el campo idioma está informado, se eliminan los registros que no cumplan el
criterio de idioma.
2. Preselección para depuración:
� Para el modo 0 (cualquier término), se obtendrán sólo registros en los que
alguno de los términos no está en el campo texto (incluye a los registros que
no tienen ninguno de los términos), dejando en base de datos el resto de
registros que son válidos sin necesidad de aplicar depuración.
� Para el modo 1 (todos los términos), se obtendrán sólo registros en los que
ninguno de los términos está en el campo texto, dejando en base de datos
el resto de registros que son válidos sin necesidad de aplicar depuración.
3. Posteriormente, se depurarán los registros obtenidos para ver si los términos que
no aparecen en el campo texto aparecen en el campo alias o en el campo url.
Con estas modificaciones se ha conseguido pasar de un tiempo de ejecución de la
función test_reco_tweets de 0:49:16.267529 a 0:25:00.411379, en una búsqueda con unos
límites de 20 minutos de ejecución o 6000 tweets recuperados:
96
Figura 52: Pruebas de estrés Streaming API (III)
Fuente: Elaboración propia
6.5.1.2 Web scraping
La instalación de herramientas y desarrollo de la solución inicial ideada para obtener
tweets del sitio web de Búsqueda Avanzada de Twitter ha generado los siguientes
problemas:
6.5.1.2.1 Filosofía inicial: BeautifulSoup4
La idea de partida para realizar scraping era usar la librería BeautifulSoup4 (en
adelante BS4), especialmente recomendada para trabajar con HTMLs desestructurados o
con una estructura compleja, como es el caso de la web de BAT.
BS4 funciona con el parser estándar de Python, pero permite instalar parsers de
terceros que pueden ser más rápidos. Se recomienda instalar lxml por ser el más efectivo
y rápido, ya que para versiones 2 de Python el parser estándar no siempre es la mejor
opción [82].
Desde el primer momento se ha tenido problemas para instalar el parser lxml. Una
vez instalados BS4 y lxml, BS4 no es capaz de reconocerlo (Figura 53).
97
Figura 53: Problemas scraping BeautifulSoup (I)
Fuente: Elaboración propia
El problema es que la versión de Python con la que se ha compilado el paquete lxml
no es la misma o no usa el mismo modo UCS para construir los paquetes (UCS2, similar a
UTF-16) que la versión de python actual (UCS4, similar a UTF-32) (Figura 54):
Figura 54: Problemas scraping BeautifulSoup (II)
Fuente: Elaboración propia
Se ha comprobado que las dependencias están instaladas, mediante
sudo dpkg -s libxml2-dev | grep Version
sudo dpkg -s libxslt1-dev | grep Version
sudo dpkg -s python-dev | grep Version
sudo dpkg -s python-libxml2 | grep Version
sudo dpkg -s python-libxslt1 | grep Version
sudo dpkg -s python-setuptools | grep Version
sudo dpkg -s zlib1g-dev | grep Version
sudo dpkg -s libxslt | grep Version
Se ha intentado la reinstalación recompilando con la versión actual de Python
mediante:
sudo pip install lxml --no-binary :all:
Pero sigue dando el mismo error, y después de dos días intentando otras opciones
se ha decidido finalmente no usarlo. Por lo que se usará el parseador por defecto, html5lib.
98
Realizando pruebas con BeautifulSoup se han detectado problemas por una
limitación específica de la librería relacionada con BAT: el sitio web de Búsqueda Avanzada
de Twitter recupera los tweets de forma dinámica a través de código JavaScript, de forma
que se van mostrando más resultados en la misma página a medida que se navega hacia
abajo a través del scroll. BS4 solo es capaz de recuperar la información de inicio que la
página web ofrece al cargarse, y que se limita sólo a los primeros resultados de la
búsqueda. Este problema ha llevado a investigar otras posibilidades:
• Scrapy: Framework completo con arquitectura propia que facilita herramientas para
gestionar el crawling completo. Recomendado sobre todo para aquellos casos en
los que se necesite necesitar aplicar scraping a varios sitios [68].
• Selenium Webdriver: Librería que simula la navegación desde el propio navegador
para poder acceder a la información del sitio web, lo que hace más complicado para
un sitio web detectar web scraping ya que su comportamiento es aparentemente
humano [69]. Selenium puede usarse de forma aislada o conjuntamente con otras
herramientas como BeautifulSoup o lxml. El problema del uso de Selenium con un
Webdriver visible (Mozilla, Chromme, etc) es la limitación de recursos que supone
levantar instancias de navegadores para ejecutarse, sobre todo si se necesita tener
levantadas varias instancias.
Selenium dispone de un paquete con Webdriver tipo headless (sin GUI) que permite
realizar simulaciones de ejecución de un navegador en background sin levantar una
instancia del mismo. Estas técnicas están siendo empleadas en soluciones de integración
continua como Jenkins, cada vez más extendidas en las empresas de desarrollo de
software [33]. Para ello hace uso de librerías tipo headless. Las más extendidas por su
rapidez, precisión y fácil acceso a los componentes de los sitios web son:
• PhantomJS: Headless WebKit (motor de diseño para la renderización de páginas
web en navegadores) basado en JavaScript que permite simular uso de navegador
sin necesidad levantar una instancia. Se puede usar conjuntamente con otras
herramientas como BeautifulSoup. Permite el acceso y manipulación de páginas
web gracias a su API para interactuar con el estándar de DOM [83].
• HTMLUnit: Headless basado en Java. Es bastante ligera y rápida, equivalente a la
ejecución de instancias de Mozilla Firefox, Google Chrome o InternetExplorer. No
99
puede emular otros navegadores que funcionen con JavaScript. Se usa con Java
[83].
En nuestro caso, se ha decidido usar Selenium + PhantomJS por permitir aplicar
técnicas de scraping efectivas, menos detectables y al mismo tiempo minimizando el uso
de los recursos disponibles evitando usar todo un framework dedicado al scraping, debido
a que en este caso sólo se necesita implementar la extracción de un solo sitio web.
6.5.1.2.2 Selenium + PhantomJS
Debido a que la página de BAT muestra los resultados de forma fraccionada y va
añadiendo resultados a los ya existentes a medida que se va bajando el scroll, es necesario
modificar la operativa ideada inicialmente para BS4 para que, en lugar de contabilizar y
comprobar el número de tweets extraídos, se contabilice y se compruebe el número de
tweets disponibles en la página para descargar. De esta forma los tweets no se extraen o
bien hasta tener cargados en página el número total de tweets deseados, o bien hasta
haber alcanzado el límite temporal definido para la búsqueda (el usuario podrá establecer,
desde la interfaz de Búsqueda del frontend, límites en cantidad y en tiempo para delimitar
la duración del proceso de extracción).
Problemas detectados una vez implementada la solución:
• PhantomJS, en su comportamiento de headless genérico no carga completamente
el contenido dinámico de BAT (le sucede con algunas páginas con JavaScript o que
procesan peticiones AJAX) y no está cargando el contenido dinámico
correspondiente a los tweets obtenidos en BAT. Para solucionarlo, Selenium
permite configurar en su webdriver, a través del objeto DesiredCapabilities [84], un
comportamiento similar a navegadores existentes como Mozilla, Chrome, etc, por
lo que se ha configurado dicho comportamiento.
• Se ha detectado que el proceso de extracción de tweets, una vez cargada la página
con todos los resultados, es lento. Se ha realizado una prueba para la extracción
de 35 tweets y el proceso ha durado 01:37 minutos (Figura 55).
100
Figura 55: Problemas Selenimum + Phantom (I)
Fuente: Elaboración propia
Para acelerar el proceso se han analizado las siguientes soluciones:
� Ejecutar el proceso de extracción mediante hilos simultáneos.
� Aplicar el uso de BS4 a la página de resultados para comprobar si su parser
es capaz de detectar los elementos de búsqueda de una forma más rápida.
Se ha conseguido solucionar el problema empleando BS4, ya que era una
de las herramientas analizadas inicialmente como opciones idóneas para el
scraping, toda vez que en este punto del desarrollo ya se tiene un html completo
con todos los tweets a extraer. Además, es la solución menos intrusiva para el
código desarrollado hasta ahora y, por otra parte, el uso de hilos requiere un
especial cuidado en su gestión. Una vez finalizada la implementación de la solución
se ha realizado otra prueba y proceso ha empleado 12 segundos en completarse,
reduciendo en algo más de un 87% el tiempo de ejecución (Figura 56).
101
Figura 56: Problemas Selenimum + Phantom (II)
Fuente: Elaboración propia
• Al ejecutar, desde el proceso de scraping, la búsqueda:
https://twitter.com/search?l=es&q=party%20OR%20verano%20near%3A%22Mála
ga%22%20within%3A15mi%20since%3A2017-03-01%20until%3A2017-04-
01&src=typd&lang=es
se están obteniendo más resultados de los que realmente recupera BAT ejecutando
la misma consulta desde la web. El problema es que en la URL se incluyen términos
con tilde, en este caso la localización (Málaga), y el uso de tildes en la URL está
causando que PhantomJS no esté teniendo el mismo comportamiento que los
navegadores compatibles definidos en la propiedad userAgent. Se han realizado
pruebas forzando la codificación de la url a 'utf8', usando varias configuraciones de
esta propiedad, y en todas se reproduce el mismo problema. Se han investigado y
probado dos posibles soluciones:
� Ejecutar una instancia visible de un navegador, en este caso Mozilla. La
extracción funciona correctamente.
� Se han realizado varias pruebas en BAT realizando búsquedas por términos
y localizaciones que contienen tildes (Figura 57), y los resultados son los
mismos que los obtenidos si no se usan tildes (Figura 58); es decir, al igual
102
que con las mayúsculas y minúsculas, BAT no hace distinción de tildes, por
lo que la solución pasa por eliminar las tildes de los términos y localizaciones
introducidos por el usuario.
Figura 57: Problemas Selenimum + Phantom (III)
Fuente: Elaboración propia
Figura 58: Problemas Selenimum + Phantom (IV)
Fuente: Elaboración propia
Se ha conseguido solucionar el problema implementando la segunda
solución, ya que la primera introduce algo de retardo en la ejecución y requiere de
103
más recursos para su ejecución al tener que ejecutar la interfaz gráfica de una
instancia de navegador.
El mismo problema de las tildes sucede en el uso de términos que contienen la letra
ñ. BAT no distingue ente n y ñ, por lo que se da como buena la solución adoptada para las
tildes, y no se realizará un nuevo nivel de filtrado en BBDD para eliminar los tweets que
contengan términos con n o ñ, según el caso, ya que el tiempo de procesado empleado
en este nuevo nivel no se ve compensado con la precisión que pueda alcanzarse en los
resultados obtenidos, al ser la ñ una letra exclusiva del idioma Español y con una frecuencia
de aparición baja [85].
• Se ha detectado que el userAgent usado durante las pruebas de un día deja de
funcionar al día siguiente. Cabe la posibilidad que BAT haya detectado la actividad
de scraping por la cantidad de pruebas lanzadas desde la misma IP y haya
bloqueado las peticiones que llegan desde la misma IP con el mismo userAgent.
Para solucionarlo, se ha definido el archivo de propiedades
useragent.properties en el que se incluye un diccionario con dos userAgent
distintos, el usado por última vez y la fecha de último uso. Y mediante una función
se cargará el userAgent que no haya sido usado el día anterior
6.5.1.2.3 Incluir / excluir retweets
Los datos ofrecidos por Streaming API y BAT incluyen tweets que son retweets de
otros. Esto podría ser considerado por el usuario como información redundante, ya que se
trata de tweets distintos, pero con el mismo texto.
Se añadirá un filtro para ofrecer al usuario, desde la interfaz de Búsqueda del
frontend, la posibilidad de incluir/excluir retweets entre los tweets recuperados por la
herramienta.
En el caso de BAT, un retweet puede indentificarse a través de la propiedad js-
retweet-text; por lo que se incluirá, en el caso en que el buscador reporte retweets y no se
desee recuperarlos, la implementación correspondiente para bloquear los tweets con esta
propiedad. Además, se ha verificado que tanto la fecha de creación del tweet que ofrece
BAT, como el número de likes y el número de retweets no son de la de creación del retweet,
sino del tweet original.
104
Para el caso de Streaming API se conservará la fecha de creación del retweet por
considerar que aporta más información saber cuándo alguien consideró un tweet
importante y lo retwitteó, pero, al igual que BAT, se obtendrán el número de likes y de
retweets del tweet original para aportar información del verdadero calado de un tweet y,
por otra parte, su obtención añadiría más complejidad, ya que la información no está
accesible en el mismo objeto usado para el acceso al resto de la información del tweet, y
sería necesario añadir nuevas comprobaciones.
6.5.1.2.4 Geolocalización de tweets recuperados
La geolocalización de los tweets no es recuperada por BAT. Sin embargo, si se abre
una nueva instancia en el navegador y se aplica scraping a la página del tweet, se puede
obtener la geolocalizaión a través de los elementos de la clase permalink-tweet-geo-text.
Se ha implementado esta solución y realizado una prueba para evaluar el tiempo
que se tarda en geolocalizar un tweet que tenga definido su posicionamiento, con un
resultado obtenido de casi 4.5 segundos (Figura 59). Lo que hace inviable plantearse
intentar geolocalizar todos los tweets, ya que, por ejemplo, en el caso de obtener una
muestra de 1000 tweets, se invertirían, como mínimo, unos 76 minutos sólo en ejecutar el
proceso de geolocalización. Esta prueba se ha realizado antes de implementar la solución
de añadir el uso de BS4 al scraping con Selenium y PhantomJS, pero al tratarse de la
búsqueda de un solo elemento, la ganancia en tiempo no sería suficiente para considerar
viable la geolocalización.
Figura 59: Geolocalización de tweets con scraping
Fuente: Elaboración propia
La solución a este problema sería el uso de hilos para lanzar en paralelo varias
ejecuciones de geolocalización, pero para ello sería necesario disponer de una máquina o
105
un servidor de gran capacidad para mantener un gran número de instancias de navegador
simultáneamente.
6.5.1.2.5 Emojis en tweets
Al obtener tweets aplicando técnicas de scraping, las funciones disponibles de la
herramienta de scraping solo reportan el texto completo del tweet sin incluir los emojis en
formato texto si estos aparecen en los textos o en los nombres/alias de los usuarios, ya
que en lugar de aparecer como parte del texto aparecen bajo etiquetas de imagen (Figura
60).
Figura 60: Emojis en tweets
Fuente: Elaboración propia
Para compensar esta pequeña pérdida de información, se ha optado por componer
y recuperar la url de la página del tweet y añadirla como un campo más, tanto en los
registros de BBDD como en la exportación a fichero, de forma que el usuario tenga la
opción de poder consultar el tweet real. En la selección de campos incluida en la ventana
de Exportación del frontend, se añadirá el campo tweet_url para incluir la URL de la página
del tweet.
En el caso de retweets, la url que se obtiene se corresponde con la url del tweet
original (tanto en los tweets obtenidos a través de Streaming API, como a través de BAT).
6.5.1.2.6 Pruebas de estrés
En el caso de scraping los factores que pueden causar problemas en el rendimiento
son:
• El proceso de obtención del html definitivo desde el webdriver headless, ya que a
medida que se van acumulando en memoria durante la búsqueda, el webdriver va
ralentizando su ejecución.
106
• El proceso de parseo del html obtenido al almacenar en un list cada estructura de
etiquetas completa asociada a un tweet, perdiéndose eficiencia a medida que se
incrementa el número de tweets contenidos en el html final.
Se han realizado algunas pruebas, en las que no se han admitido retweets para
forzar a que el proceso realice el máximo de operaciones.
Se ha probado la extracción y exportación a fichero de tweets con límite temporal
de 20 minutos y un máximo muy elevado tweets con la siguiente url de búsqueda:
https://twitter.com/search?l=&q=clima%20OR%20global%20since%3A2009-01-
01%20until%3A2014-12-31&src=typd&lang=es
Con estos parámetros se han obtenido 1159 tweets, invirtiendo un tiempo total de
0:26:12.872245 en completar el proceso (Figura 61).
Figura 61: Pruebas de estrés scraping (I)
Fuente: Elaboración propia
Se ha probado la extracción y exportación a fichero de tweets límite temporal de 30
minutos y un máximo tweets elevado con la siguiente url de búsqueda.
https://twitter.com/search?l=&q=ronaldo%20OR%20messi%20since%3A2011-01-
01%20until%3A2017-07-01&src=typd&lang=es
Con estos parámetros, se han obtenido 1429 tweets, invirtiendo un tiempo total de
0:39:14.703187 en completar el proceso (Figura 62).
107
Figura 62: Pruebas de estrés scraping (II)
Fuente: Elaboración propia
Se ha realizado una prueba con webdriver visible de Mozilla, en lugar de webdriver
headless como PhantomJS, usando la misma url anterior, y se han obtenido 1179 tweets,
invirtiendo un tiempo total de 0:26:50.890141 en completar el proceso (Figura 63).
Figura 63: Pruebas de estrés scraping (III)
Fuente: Elaboración propia
Se ha comprobado que al scrapear BAT, durante la de recopilación de tweets antes
de su extracción, el proceso se ralentiza a medida que se incrementa el número de tweets
cargados en la web, debido al volumen de información en memoria, mientras se añaden
más tweets al ejecutar la acción de bajar el scroll, y realizar el conteo de los acumulados.
El problema era que la comprobación de límites alcanzados dentro de la operativa
de bajada de scroll estaba ralentizando el proceso. Se ha reordenado la operativa de
comprobación y bajada de scroll, y el proceso recopila y obtiene tweets más eficientemente.
Se han realizado algunas pruebas de extracción de tweets con límite temporal de
20 minutos y un máximo tweets elevado con la siguiente url de búsqueda, y empleando
varias implementaciones para intentar mejorar la eficiencia:
https://twitter.com/search?l=&q=ronaldo%20OR%20messi%20since%3A2011-01-
01%20until%3A2017-07-01&src=typd&lang=es
• sleep(30) fuera de bajar scroll: se han obtenido 5688 tweets.
• sleep(10) fuera de bajar scroll: se han obtenido 5816 tweets.
• sleep(1) dentro de bajar scroll: se han obtenido 6256 tweets.
108
• sleep(1) dentro de bajar scroll y sleep(10) dentro de bucle de comprobación de
página cargada: se han obtenido 6349 tweets.
• sleep(2) dentro de bajar scroll y sleep(10) dentro de bucle de comprobación de
página cargada: se han obtenido 6239 tweets.
• sleep(1) dentro de bajar scroll y sleep(20) dentro de bucle de comprobación de
página cargada: se han obtenido 6346 tweets.
• sleep(1) dentro de bajar scroll y sleep(60 dentro de bucle de comprobación de
página cargada: se han obtenido 6328 tweets.
• Usando webdriver Firefox y controlando en el bucle de comprobación de página
cargada si uno de los elementos a pie de página (stream-footer o try-again-after-
whale) están visibles (indicador de fin de carga): se han obtenido 3682 tweets.
Por tanto, se concluye que la mejor opción es sleep(1) dentro de bajar scroll y
sleep(10) dentro de bucle de comprobación de página cargada. Se ejecuta una nueva
prueba completa (extracción y exportación) con esta implementación (Figura 64).
Figura 64: Pruebas de estrés scraping (IV)
Fuente: Elaboración propia
Finalmente, con el objetivo de reducir el elevado tiempo de ejecución de la prueba
anterior, se ha optado por reorganizar el código e introducir el uso de hilos simultáneos a
la hora de extraer cada tweet del html resultante de la búsqueda. Además, se ha mejorado
también la exportación de ficheros según se comenta más adelante, y en la prueba final de
extracción y exportación conjunta se ha conseguido obtener una mayor cantidad de tweets
que en las primeras implementaciones y reducir los tiempos totales del proceso (Figura
65).
109
Figura 65: Pruebas de estrés scraping (V)
Fuente: Elaboración propia
Sobre los tiempos de ejecución de la exportación a fichero comentada
anteriormente, se observó que las ejecuciones de la función de exportación a fichero se
ralentizaban después de la ejecución de las funciones de scraping cuando se ejecutaban
dentro de la misma prueba.
En las pruebas realizadas con la Streaming API la exportación es más ágil, por
ejemplo, en una de las pruebas se exportó 4826 tweets en menos de 3 minutos.
Con el objetivo de agilizar el proceso de exportación a fichero de los registros
almacenados en base de datos, se han realizado pruebas de exportación aisladas con dos
implementaciones distintas:
• Inserción de líneas en fichero mediante el hilo principal del proceso.
• Inserción de líneas en fichero mediante el uso de hilos de ejecución simultáneos.
110
Se ha realizado una prueba conjunta (extracción y exportación) con hilos: la
exportación de 2957 tweets ha durado algo más de 9 minutos (Figura 66).
Figura 66: Pruebas de estrés scraping (VI)
Fuente: Elaboración propia
Se ha realizado una prueba conjunta (extracción y exportación) sin hilos: la
exportación de 2952 tweets ha durado algo más de 11 minutos (Figura 67).
Figura 67: Pruebas de estrés scraping (VII)
Fuente: Elaboración propia
Se ha comprobado que el uso de hilos simultáneos en este caso no agiliza la
inserción de líneas. En cualquier caso, la ejecución de forma aislada de la función exportar
sin hilos es bastante más rápida.
Se ha realizado una prueba aislada con hilos: ha tardado más que la ejecución sin
hilos y a además se detecta la pérdida de un registro (Figura 68).
Figura 68: Pruebas de estrés scraping (VIII)
Fuente: Elaboración propia
111
Se ha realizado una prueba aislada con hilos y con bloqueo de fichero (self.lock =
threading.Lock()): Se detecta la pérdida de 6 registros y el proceso ha tardado algo menos
que la ejecución con hilos anterior. Si un hilo intenta acceder al recurso, muere sin insertar
la línea. Se podría añadir el reintento hasta que el recurso esté libre, incurriendo en una
mayor demora en la ejecución del proceso; motivo por el cuál directamente se descarta
esta opción (Figura 69).
Figura 69: Pruebas de estrés scraping (IX)
Fuente: Elaboración propia
Finalmente se ha mejorado la implementación de hilos reorganizando el código y el
proceso ha mejorado considerablemente, el contador de tweets parece que no es correcto,
pero el número real de tweets incluido en el fichero sí es correcto. Se ha solucionado
reemplazando el contador de líneas por la ejecución de la instrucción wc -l una vez
generado el fichero (Figura 70).
Figura 70: Pruebas de estrés scraping (X)
Fuente: Elaboración propia
6.5.2 FrontEnd
6.5.2.1.1 Carga dinámica de librería API Google Maps
De forma análoga a las claves de acceso a la API de Twitter, se permitirá al usuario
configurar la clave de autenticación a la API de Google Maps en el mismo panel de
configuración de acceso a Twitter, cargando la referencia a la API de Google Maps con la
clave de autenticación.
112
Se han producido problemas en la carga dinámica de las librerías debido a que,
durante este proceso, Google automatiza la carga de otras librerías entre las que se
encuentra la responsable del proceso de autenticación. Para reducir posibles problemas,
antes de realizar la nueva carga, se eliminarán todas las librerías relacionadas, aunque la
carga adicional que realiza la API de Google provoca que, en el caso de modificar la clave
una vez cargada una previa, no todas las librerías previas relacionadas con la carga
anterior sean eliminadas, debido al carácter asíncrono de su funcionamiento. Sin embargo,
no se han detectado efectos erróneos en la herramienta relacionados con este problema.
La API ofrece una funcionalidad para la detección de errores de autenticación. El
proceso de autenticación y respuesta consume no más de 1 segundo, por lo que se
recomienda al usuario de la herramienta que, una vez informadas las credenciales y
solicitado su almacenamiento pulsando el botón guardar, esperar unos instantes antes de
comenzar a trabajar ya que la ejecución de llamadas a las funciones de la API interfiere en
el proceso de autenticación, y podría no detectarse algún posible error causado por el uso
de una clave incorrecta.
En todo caso, se ha probado que, si la herramienta no muestra un mensaje de error
relacionado con la clave de autenticación y sin embargo no carga el mapa de
geolocalización, la causa es un error de autenticación, por lo que se recomienda reiniciar
la aplicación, volver a cargar la clave de autenticación y esperar unos instantes antes de
usar los controles de geolocalización. No obstante, la herramienta solo permitirá la carga
del panel de geolocalización si se detecta la configuración previa de la clave de acceso a
la API de Google Maps. Si el campo de clave para el acceso a la API de Google Maps no
está informado, no se permitirá incluir información de geolocalización en la búsqueda.
Por último, se ha detectado un problema de asincronía producido en la
geocodificación de las localizaciones al asignar a variables la información obtenida a través
de la funcion geocode, ya que el flujo de ejecución continúa sin esperar la finalización del
servicio. Después de varias pruebas, se ha solucionado el problema mediante el uso de la
funcion de JQuery setTimeout(), que permite establecer un temporizador para ejecutar
bloques de instrucciones.
6.5.2.1.2 Códigos de idioma en Twitter
Se han detectado algunas discrepancias en los códigos de idioma utilizados como
filtros en las búsquedas por las APIs de Twitter [87] y por BAT [31], así como los que se
113
obtienen como resultado de las búsquedas a través del scraping de BAT. Por ejemplo, el
idioma Malayo es codificado en API con el valor "msa", y en BAT como "ml". O, por ejemplo,
el inglés, en la API de Twitter se distinguen dos variantes: “en” (inglés) y “en-gb” (inglés
británico); mientras que en BAT sólo se reconoce el código “en”. Además, el número de
idiomas soportado por BAT es mayor que el de las APIs. Esta diferencia puede inducir a
resultados erróneos en las búsquedas que se realicen por idioma, ya que desde la
herramienta podría seleccionarse un idioma que no aparezca en la fuente de destino.
Para solucionar el desalineamiento, ha sido necesario unificar ambos listados para
poder ofrecer soporte común de idioma en la herramienta, por lo que no se ofrecerán, para
los filtros de búsqueda los idiomas que no estén incluidos en las dos plataformas.
114
7 RESULTADOS Y DISCUSIÓN
En este apartado se realizará un análisis de los resultados obtenidos, en función de
los objetivos y el desarrollo del presente trabajo. El objetivo principal es la construcción de
una herramienta para la obtención de opiniones (tweets) en Twitter, que permita realizar
consultas a la red social, usando un conjunto de cláusulas para delimitar un subconjunto
de tweets de muestra, y además poder exportar los resultados a un fichero para conformar
corpus de información.
Una vez realizado el análisis sobre la forma de acceder y la información a descargar,
las opciones para al acceso se reducen principalmente por el carácter comercial que, las
empresas y los sistemas de información en general, y en este caso Twitter en particular,
otorgan a la información generada a partir de las opiniones y comentarios que
constantemente se publican en las redes.
Teniendo en cuenta esta premisa, la herramienta desarrollada permite el acceso a
tweets publicados en cualquier ventana temporal del histórico de Twitter, con las únicas
restricciones relativas a la cantidad de información, y al acceso a servicios tales como la
conversión de URLs en formato corto a formato normal, o la geolocalización de posiciones
determinadas por sus coordenadas geográficas; impuestas por el carácter gratuito de su
acceso.
En base al análisis de la información accesible de Twitter, como parte de los
objetivos iniciales, se han incluido varias opciones de búsqueda como motor de la
herramienta, que ofrecen la posibilidad de filtrar por criterios muy útiles a la hora de
conformar corpus de información para su procesado, por ejemplo, por herramientas
destinadas al análisis de sentimientos con respecto a un producto, servicio, situación
política, etc.; obteniendo la información más representativa sobre un hecho, como es la
publicación de una opinión: ¿qué y cómo? (texto), ¿quién? (id, nombre, alias), ¿cuándo?
(fecha), ¿dónde? (localización, latitud, longitud); además de otra información que
actualmente empieza a cobrar importancia: ¿opinión propia? (retweet), ¿cuántos lo han
repetido? (nretweets), ¿a cuántos les gusta lo que dice? (nlikes). En la Figura 71 puede
observarse un ejemplo de la información obtenida en una búsqueda.
115
Figura 71: Campos fichero
Fuente: Elaboración propia
La base de búsqueda en la herramienta es el filtrado por los términos que deben
aparecer en los textos de los tweets; dando libertad al usuario para decidir si los términos
elegidos deben estar todos presentes en el texto, o solo algunos. Además, se permite la
búsqueda con caracteres especiales, tales como tildes o la ñ, como se puede observar en
los términos de búsqueda y resultados de la Figura 72 y la Figura 73.
Figura 72: Términos de búsqueda
Fuente: Elaboración propia
Figura 73 Resultados búsqueda
Fuente: Elaboración propia
Otro aspecto importante a la hora de realizar una búsqueda, es poder elegir la
ventana temporal sobre la que extraer información, por ejemplo, para contrastar la
evolución de las opiniones sobre cualquier asunto y facilitar la toma de decisiones por parte
de una entidad, o bien saber el impacto de una noticia en el momento de producirse, con
el objetivo de analizar comportamientos sociales, etc. Para ello, la herramienta ofrece la
posibilidad de definir unas fechas de inicio y fin con las que acotar una búsqueda, o bien,
capturar las opiniones instantáneas a medida que estás se van publicando, como se
observa en la Figura74 y en la Figura 75.
116
Figura 74: Parámetros fechas
Fuente: Elaboración propia
Figura75: Resultados fecha
Fuente: Elaboración propia
Términos y fechas son las cláusulas que pueden determinar un mayor o menor
volumen de información potencial para su descarga, pero no son las únicas. El resto de
opciones incluidas en la herramienta ( idioma, retweets y localización) también son
bastante útiles y se ha comprobado que el uso conjunto de ellas permite acotar con
bastante precisión la muestra de tweets deseada. Por ejemplo, se ha realizado una
búsqueda de corta duración empleando los términos “Cataluña” e “independencia”, en
idioma español, incluyendo retweets, sin filtro de localización y sin fechas para acceder a
la información instantánea, con la intención de conocer opiniones de usuarios sobre la
situación actual de la independencia catalana; y la muestra obtenida de tweets (Figura 76)
responde a una precisión total en contenido (la independencia de Cataluña), con respecto
a las cláusulas usadas para la búsqueda.
Figura 76: Resultado tweets
Fuente: Elaboración propia
117
Otro de los objetivos buscados con la herramienta era la posibilidad de exportar a
fichero los resultados de las búsquedas. El resultado final facilitado por la herramienta,
ofrece la posibilidad de seleccionar el volumen de información a exportar en base a un
rango de fechas, un nombre de localización, y el nombre de uno, varios dominios o toda la
base de datos. Además, se pueden seleccionar los campos a exportar, así como el formato
de exportación (txt o csv). En el ejemplo de la Figura 77 se ha realizado el cálculo del
volumen de tweets de dos colecciones para su descarga, con un total de 314 tweets, y se
ha descargado en dos ficheros (uno en formato csv, y otro en formato txt) que incluyen
todos los tweets calculados previamente (314 + línea de cabecera).
Figura 77: Resultado exportación
Fuente: Elaboración propia
Además, la herramienta contempla la doble posibilidad de realizar búsquedas
geolocalizadas (Figura 78) y obtener información de geolocalización en la información
obtenida (Figura 79), opciones que, al comienzo de este trabajo, no eran objetivo prioritario,
debido a su baja incidencia, pero que se han considerado como un extra interesante para
enriquecer los resultados obtenidos.
118
Figura 78: Filtro geolocalización
Fuente: Elaboración propia
Figura 79: Resultados geolocalización
Fuente: Elaboración propia
Finalmente, hay otros aspectos de la herramienta que, aunque no formaban parte
de los objetivos principales, se han implementado con éxito, como son:
• Visualización de las estadísticas de volumen global, por dominios (Figura 80) y
estadísticas independientes por localización y por idioma, de toda la información en
base de datos (Figura 81).
Figura 80: Estadísticas globales
Fuente: Elaboración propia
119
Figura 81: Estadísticas parciales
Fuente: Elaboración propia
• Posibilidad de gestionar la eliminación de dominios (Figura 82).
Figura 82: Gestión de dominios
Fuente: Elaboración propia
• Posibilidad de parametrizar, desde la propia interfaz de la aplicación, las
credenciales de acceso a las APIs de Twitter y de Google Maps, dando a la
aplicación un carácter de multiusuario (Figura 83), al permitir su uso simultáneo por
más de un usuario con sus propias credenciales.
120
Figura 83: Configuración credenciales
Fuente: Elaboración propia
• El envío seguro de la información a través del cifrado SSL (Figura 84).
Figura 84: Cifrado SSL
Fuente: Elaboración propia
121
8 CONCLUSIONES
A continuación, se exponen las conclusiones alcanzadas a la finalización del
presente trabajo.
Desde el punto de visa de los resultados obtenidos, expuestos en el apartado
anterior, pueden considerarse alcanzados todos los objetivos marcados al inicio de este
trabajo. La herramienta desarrollada cumple satisfactoriamente con todos los requisitos,
permitiendo además la extracción de tweets a través de una herramienta sencilla e intuitiva.
Se consideran acertadas las tecnologías empleadas para la implementación de la
solución, destacando la flexibilidad de Python para el desarrollo en el lado servidor, que ha
permitido la implementación de una solución completa, facilitando la rápida adaptación a
un entorno de desarrollo marcado por constantes cambios, poniendo de relieve la
necesidad de adaptar cualquier solución software a las posibilidades ofrecidas por una
cantidad cada vez más elevada de APIs.
Como consecuencia de lo anterior, se concluye como acertada la decisión de
desarrollar la herramienta como aplicación web en lugar de aplicación de escritorio, ya que
ha facilitado la integración de los cambios acometidos para solucionar problemas
detectados durante el desarrollo.
Por otra parte, el desarrollo de una herramienta para el acceso a la información de
una red social como Twitter, proporciona una visión del potencial generado por la cantidad
ingente de información publicada cada día, haciendo de esta un nicho de oportunidades en
la investigación y análisis de comportamientos sociales. En este sentido, Twitter, aunque
ofrece diversas posibilidades para el acceso a la información a través de sus APIs, limita
el alcance al volumen de información libre ofrecida.
Por último, la involucración necesaria en aspectos del desarrollo relacionados con
el frontend y el backend ofrece una visión completa sobre el ciclo de desarrollo de una
herramienta software, favoreciendo la adquisición de competencias que facilitan el análisis
global de posibles soluciones a problemas planteados. En el caso de esta herramienta, han
posibilitado, por ejemplo, el análisis de alternativas para el acceso a la información de
Twitter, que se ha traducido en la implementación de una API de scraping totalmente
personalizada y efectiva.
122
8.1 Limitaciones
A lo largo del desarrollo se han detectado algunos puntos que pueden limitar el
alcance del funcionamiento de la herramienta. A continuación, se describen brevemente.
1. Cambios en las APIs de Twitter: Con motivo de la reunificación de la plataforma
API, Twitter está acometiendo una serie de cambios que van desde la estructura de
los objetos de información (Tweet, Users, etc.), hasta las condiciones y forma de
acceso. Parte de la primera fase de este cambio ha sido completada hace apenas
unas semanas con la puesta en marcha de la nueva plataforma de documentación,
que supone un cambio estructural y de contenido con respecto a la anterior, origen
de la documentación del presente trabajo. Por este motivo, tanto a nivel de
documentación como a nivel técnico, supone una gran limitación cuyo impacto se
describe en el apartado 5.1.1 Impacto de cambios previstos en Twitter.
2. Accesibilidad de las APIs de Twitter: La accesibilidad a las APIs de Twitter han
supuesto una limitación en este trabajo debido a las restricciones asociadas a su
carácter gratuito, que limitan en conexiones, ventana temporal y volumen, el acceso
a la información, lo que convierte en insuficientes las formas oficiales de acceso a
la información.
3. Servicios gratuitos de geocode y conversión de URLs: El uso de servidores gratuitos
para la geolocalización de los tweets y la obtención de URLs está limitado por las
políticas de uso de dichos servicios, que generan errores por timeout, o incluso
pueden generar el bloqueo temporal al servicio. Esta circunstancia ha obligado
buscar formas de reorganizar el código fuente con el objetivo de minimizar las
llamadas a los servicios, impactando en otras funcionalidades, como el uso del
campo place en los tweets en el caso de geolocalización, cuya información de
posicionamiento no tiene por qué ser la del lugar desde el que se generan
realmente. Por otra parte, la generación de errores se traduce en pérdidas de
información durante el procesado de los tweets.
4. Geolocalización de tweets a través de scraping: Durante el desarrollo se ha
detectado que BAT no ofrece información de geolocalización, y se ha analizado
como alternativa el scrapeo de la propia página de cada tweet, en la que sí podría
estar informada. Sin embargo, se ha descartado debido a que la solución
encontrada requiere el uso de hilos en paralelo lo implica una limitación técnica, ya
123
que se necesitaría mantener varias instancias del webdriver levantadas, para lo que
se necesita un servidor de gran capacidad.
8.2 Líneas de futuro
De cara una nueva versión de la herramienta, hay algunos puntos que se podrían
mejorar e incorporar como pequeños evolutivos, para ofrecer más información al usuario.
A continuación, se describen brevemente algunos de ellos.
1. Se podría analizar la forma de extraer los emojis que, bajo etiquetas de imagen,
suelen aparecer en los nombres/alias de los usuarios y en los textos en los tweets
recuperados en el scraping de BAT.
2. En la ventana de cálculo de estadísticas, se podría incluir, dentro del cálculo global,
el cálculo total de tweets por idioma y localización.
3. En el cálculo de estadísticas de la ventana de Exportación, una posible mejora
podría ser permitir incluir más de una localización en el filtro de localizaciones, e
incluir el idioma como parte del filtro para la descarga, ampliando, de esta manera,
el alcance de la descarga.
4. Por otra parte, para una versión futura, se podría analizar la posibilidad de permitir
lanzar peticiones de búsqueda a la Streaming API y a BAT de forma paralela, para
agilizar la adquisición de datos.
En cuanto a evolutivos de gran alcance, se podrían implementar dos
fundamentalmente:
1. Ampliación de tareas a ejecutar por la herramienta, incluyendo labores propias de
Procesamiento de Lenguaje Natural y Análisis de Sentimientos de los corpus
obtenidos en base de datos.
2. Ampliación del alcance de la herramienta, analizando la viabilidad de implementar
un módulo de acceso a la API de otra red social de uso masivo, como es el caso de
Facebook, de manera que puedan formarse corpus de ambas redes sociales, e
incluso cruzar información entre ambas.
124
9 GLOSARIO DE TÉRMINOS
API: Application Programming Interface. Conjunto de funcionalidades que permiten
la asbtracción, a nivel de programación, de particularidades relacionadas con las
estructuras internas de módulos, librerías, o su conjunto.
Análisis de Sentimiento s: Técnicas para la clasificación de documentos en función
de la polaridad (negativa, positiva o neutra) expresada en ellos por sus autores.
BSON: Binary JSON. Representación binaria del formato JSON. Es empleada por
la base de datos MongoDB para la gestión interna de la información.
Big Data : Masiva cantidad de información no estructurada junto con el conjunto de
técnicas para su procesamiento y análisis.
Inteligencia Artificial : Emulación del comportamiento de la mente humana por
parte de las máquinas.
Internet de las cosas : Interconexión de objetos (sensores, dispositivos, etc) de uso
común a través de Internet.
JSON: JavaScript Object Notation. Formato de representación de la información
orientado a agilizar su intercambio, similar a otros formatos como XML.
OAuth : Open Authorization. Estándar de autorización empleado en sitios web que
permite el acceso a información de un usuario sin acceder a toda la información sobre su
identidad.
Open Data : Datos que son ofrecidos de forma pública sin restricciones de control
sobre su uso.
Procesamiento del Lenguaje Natural : Parte importante de la Inteligencia Artificial.
Conjunto de técnicas destinadas al análisis del uso del lenguaje para el diseño de
mecanismos de comunicación computacionalmente eficaces. PLN es una parte importante
de la IA.
125
REST: Representational State Transfer. Tipo de arquitectura web para la
comunicación entre cliente y servidor basada en el estándar HTTP, que permite el
intercambio de información sin estados, en el que toda la información requerida para el
acceso a un recurso viaja en la propia petición del cliente.
SSL: Secure Sockets Layer. Protocolo de comunicación que proporciona integridad
y seguridad en el intercambio de información entre cliente y servidor.
Smart Cities : Ciudades inteligentes. Ciudades que emplean recursos relacionados
con las tecnologías de la información para facilitar servicios que garanticen la sostenibilidad
económica, social y medioambiental.
URI: Uniform Resource Identifier. Identificador unívoco de recursos que pueden ser
accedidos en una red.
Webdriver : Interfaz para el control remoto de instancias de un navegador web.
Análisis de redes sociales : Conjunto de técnicas orientadas al estudio de las
relaciones establecidas (generación, impacto, etc.) entre los miembros de una red.
Backend y Frontend : Términos empleados para designar a las partes de una
aplicación destinadas a la gestión y procesado de la información (backend), y a la
visualización de los resultados (frontend).
Endpoint : Conjunto de métodos ofrecidos por una API para el acceso a la
información.
Full stack : Término para designar el ciclo de desarrollo de una aplicación que
abarca todos los aspectos relativos al backend y al frondend.
Listener : Proceso destinado a la recepción de peticiones para la gestión del tráfico
de información.
Microblogging : Servicio de envío y publicación de mensajes cortos, generalmente
de texto.
126
Parser : Analizador sintáctico destinado al análisis de información (símbolos) según
unas reglas de estructura normalizadas.
Tweet : Opinión publicada por una persona o entidad en la red social Twitter.
127
10 ANEXOS
10.1 Mensajes de error devueltos por API standard
Figura 85: Códigos Error API standard (I)
Fuente: Response Codes [88]
128
Figura 86: Códigos Error API standard (II)
Fuente: Response Codes [88]
129
Figura 87: Códigos Error API standard (III)
Fuente: Response Codes [88]
130
Figura 88: Códigos Error API standard (IV)
Fuente: Response Codes [88]
131
10.2 Códigos de error HTTP asociados a Streaming AP I
Figura 89: Códigos de error HTTP asociados a Streaming API (I)
Fuente: Filter Realtime Tweets [89]
132
Figura 90: Códigos de error HTTP asociados a Streaming API (II)
Fuente: Filter Realtime Tweets [89]
10.3 Pasos previos para usar la API de Twitter
El uso de las APIs de Twitter requiere autenticación a través del protocolo OAuth,
que proporciona acceso limitado a través de un servicio HTTP. Para poder acceder a las
APIs y realizar llamadas a sus funciones, son necesarios tokens de acceso al protocolo
OAuth, que serán emitidos en nombre de un usuario o una aplicación dependiendo de la
API y la funcionalidad que se desee implementar [20].
Para el caso de la herramienta desarrollada en este trabajo, se obtendrán los tokens
para el usuario propietario de la aplicación [90]. Para ello es necesario crear una aplicación
en Twitter, de forma que se le puedan asignar los tokens de acceso, que identifican a la
aplicación para comunicarse con las APIs de Twitter.
A continuación, se detallan los pasos a seguir:
1. Si no se tiene usuario en Twitter, crear uno a través de la URL:
https://twitter.com/signup?lang=es
133
2. Acceder a la interfaz de aplicaciones a través de la siguiente URL, usando para ello
el usuario / password de la cuenta de Twitter (Figura 91):
https://twitter.com/login?redirect_after_login=https%3A/apps.twitter.com/
Figura 91: Acceso a la interfaz de aplicaciones
Fuente: Twitter Apps [91]
Al acceder, se redirecciona a la URL (Figura 92):
https://apps.twitter.com/
Figura 92: Interfaz de aplicaciones
Fuente: Twitter Apps [91]
Si no se ha redireccionado, acceder manualmente.
3. Crear una aplicación. Para ello, hacer click en el botón “Create New App” y rellenar
el formulario al que redirige (Figura 93), al menos con los datos obligatorios para la
aplicación:
134
� Name: Se puede usar cualquier nombre, siempre que no se haya usado
antes.
� Description: Indicar una breve descripción de la aplicación.
� Website: URL de la aplicación. Si no se dispone de una URL real, indicar
una ficticia. Por ejemplo: https://www.url-ficticia-para-crear-app.com
Marcar el check “Yes, I have read and agree to the Twitter Developer
Agreement.” y hacer click en el botón “Create your Twitter application”.
Figura 93: Formulario para crear una aplicación
Fuente: Twitter Apps [91]
135
4. Crear claves y tokens de acceso. Al crear la aplicación el propio flujo redirige a la
pantalla de gestión de la aplicación. En ella, seleccionar la pestaña “Key and Access
Tokens” (Figura 94).
Figura 94: Generación de claves y tokens de acceso
Fuente: Twitter Apps [91]
El password de acceso a las APIs de Twitter consta de cuatro partes: las
claves API Key y API Secret, y los tokens Access Token y Access Token Secret.
Se recomienda regenerar las claves de acceso. Para ello pulsar en
“Regenerate Consumer Key and Secret”.
136
Por último, es necesario generar los tokens para asociarlos a claves. Para
ello, pulsar en “Create my Access token”. Una vez generados estarán disponibles
en la misma ventana, en el apartado “Your acces Token”.
Las claves y tokens generados son confidenciales, por lo que no deben ser
compartidos. Estos deberán incluirse en la cabecera de autorización añadida en las
peticiones HTTP usadas para enviar solicitudes autorizadas a las APIs de Twitter.
10.4 Generación de certificado SSL con autofirma
Los pasos necesarios para la generación de un certificado SSL con autofirma son
los siguientes [92]:
1. Instalar OpenSSL sino está instalado en el sistema
sudo apt-get install openssl
2. Generar clave privada
openssl genrsa -out server.key 1024
3. Crear solitiud de firma de certificado CSR (Certificate Signing Request)
openssl req -new -key server.key -out server.csr
4. Completar información requerida por la petición. Por ejemplo:
Country Name (2 letter code) [GB] :SP
State or Province Name (full name) [Berkshire] :Jaen
Locality Name (eg, city) [Newbury] :Linares
Organization Name (eg, company) [My Company Ltd] : My company
Organizational Unit Name (eg, section) [] :Information Technology
Common Name (eg, your name or your server's hostname) [] : mycomany.com
El resto de preguntas solicitadas se puede dejar en blanco.
5. Generar certificado SSL:
137
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
6. Copiar ficheros SSL generados a /etc/ssl/certs
sudo cp server.crt /etc/ssl/certs/ssl.crt
sudo cp server.key /etc/ssl/certs/ssl.key
10.5 Instrucciones para la cargar fichero csv gener ado en Microsoft
Excel
Para abrir los ficheros csv generados por la herramienta y exportarlos a una hoja
de cálculo, en Excel 2016, los pasos a seguir son los siguientes:
1. Abrir una nueva hoja en Excel.
2. En el menú Datos, seleccionar la opción Obtener Datos Externos -> Desde un
archivo de texto.
3. Elegir fichero y pulsar en Importar. En el asistente para importar:
4. Modificar el Origen de archivo, seleccionar Unicode (UTF-8) y marcar check Mis
datos tienen encabezados.
5. Pulstar en Siguiente.
6. Marcar como separador la opción Tabulador y modificar Calificador de texto
seleccionando ' (comilla simple).
7. Pulsar en Siguiente.
8. Seleccionar todas las columnas y en Formato de los datos en columnas seleccionar
la opción Texto.
9. Pulsar en Finalizar.
10. Seleccionar Importar en una hoja nueva y pulsar en Aceptar.
10.6 Manual de usuario
Una vez instalada la aplicación y arrancados lo servidores de Apache y MongoDB,
según se describe el punto 10.7 Manual de instalación del presente documento, la
aplicación estará disponible a través de la URL:
https://recotweets.com/index.html
138
A continuación se describe el funcionamiento de la herramienta a través de las
opciones habilitadas en la interfaz visual.
10.6.1 Ventana Principal
La ventana principal de la aplicación consta de un panel de navegación con las
interfaces de trabajo (Figura 95): Búsqueda, Visualización, Gestión y Exportación.
Figura 95: Ventana Principal
Fuente: Elaboración propia
Al pasar el cursor por encima de cada opción se mostrará una breve descripción de
su funcionalidad (Figura 96).
Figura 96: Panel de navegación
Fuente: Elaboración propia
Por defecto, la interfaz mostrada al acceder a la aplicación es la de Búsqueda.
Para acceder a cada una de las interfaces basta con pulsar la opción deseada, bien
en el panel de navegación, o bien en uno de los indicadores de ventana situados al pie de
139
página (Figura 97). El indicador de color negro se corresponde con la interfaz activa y, al
pasar el cursor por encima de cada uno de los indicadores, se mostrará una breve
descripción de su funcionalidad. En general, todos los botones y checks de la aplicación
ofrecen un mensaje descriptivo al situar el cursor encima.
Figura 97: Indicadores de ventana
Fuente: Elaboración propia
Todas las interfaces tienen varios elementos comunes:
• Etiquetas informativas con el nombre y descripción de la interfaz: Situadas debajo
del panel de navegación (Figura 98).
Figura 98 Etiqueta inormativa
Fuente: Elaboración propia
• Botones de Mostrar todo/Ocultar todo: Situados también a pie de página (Figura
99), permiten desplegar o cerrar todos los panes de la interfaz activa.
Figura 99: Botones Mostrar todo/Ocultar todo
Fuente: Elaboración propia
10.6.2 Interfaz de Búsqueda
Permite la gestión de las credenciales de usuario necesarias, así como la definición
de las opciones de búsqueda y su ejecución (Figura 100).
140
Figura 100: Interfaz de Búsqueda
Fuente: Elaboración propia
A continuación se describen sus paneles y controles.
10.6.2.1 Panel Configuración
Para ejecutar las búsquedas es condición necesaria que todos los campos estén
informados y la configuración almacenada en la base de datos (Figura 101).
Figura 101: Panel Configuración
Fuente: Elaboración propia
Las operaciones habilitadas son las siguientes:
141
• Alta de usuario: Para ello es necesario rellenar todos los campos y pulsar en el
botón Guardar configuración (Figura 102).
Figura 102: Botón Guardar configuración
Fuente: Elaboración propia
• Baja de usuario: Para ello es necesario rellenar los campos de Usuario y Password,
y pulsar el botón Eliminar configuración (Figura 103).
Figura 103: Botón Eliminar configuración
Fuente: Elaboración propia
• Carga de usuario: Para ello es necesario rellenar los campos de Usuario y
Password, y pulsar el botón Cargar configuración (Figura 104). En caso de estar
cargada la configuración de otro usuario, será necesario habilitar la edición de los
dichos campos pulsando el botón Editar configuración (Figura 105).
Figura 104: Cargar configuración
Fuente: Elaboración propia
Figura 105: Editar configuración
Fuente: Elaboración propia
Los botones para gestionar las operaciones descritas se habilitarán/deshabilitarán
de forma automática según las necesidades de cada momento.
10.6.2.2 Panel Tema / Dominio
142
Consta de un campo para asignar el nombre a la colección de base de datos que
almacenará los tweets recuperados en una búsqueda (Figura 106). No permite la
introducción de caracteres que no sean alfanuméricos, tampoco admite tildes ni la letra ñ.
En caso de detectarse esta circunstancia, la aplicación generará un mensaje de aviso. Es
obligatorio rellenar este campo para ejecutar una búsqueda.
Figura 106: Panel Tema / Dominio
Fuente: Elaboración propia
10.6.2.3 Panel Opciones de Búsqueda
Consta de los campos por los cuales se realizará el filtrado de tweets de la
búsqueda (Figura 107).
Figura 107: Panel Opciones de Búsqueda
Fuente: Elaboración propia
Los campos son los siguientes:
• Términos: Permite incluir un listado de palabras separadas por “,”. Es obligatorio
rellenar este campo para ejecutar una búsqueda.
• Modo: Indica si todos los términos deben aparecer en el texto de los tweets, o si
pueden aparecer cualquiera de ellos.
• Retweets: Marcar el check para que la búsqueda incluya retweets.
143
• Fecha inicio: Pulsar en su icono para desplegar un calendario y seleccionar una
fecha de inicio. Los tweets buscados serán los que hayan sido publicados con fecha
superior a la seleccionada.
• Fecha fin: Pulsar en su icono para desplegar un calendario y seleccionar una fecha
de fin. Los tweets buscados serán los que hayan sido publicados con fecha inferior
a la seleccionada.
• Idioma: Pulsar en su icono para desplegar una lista con los idiomas disponibles. Si
el campo no se rellena, la búsqueda se ejecutará por defecto para todos los idiomas.
• Localización: Puede rellenarse de dos formas:
La primera forma es escribiendo el nombre de la localización directamente en el
campo y pulsar en cualquier punto vacío de la pantalla, dejando un margen de unos
segundos para que la aplicación calcule las coordenadas y reescriba en el campo el
nombre oficial que Google Maps tiene asignado a esa localización.
La segunda forma es pulsando el icono de apertura de mapa para cargar el panel
de Geolocalización, comentado más adelante.
• Places: Solo afecta a las búsquedas sin fecha. Marcar si se desea que la
información de geolocalización de los tweets recuperados sea la que cada tweet
tenga configurada por defecto.
• Tiempo MAX: Tiempo en minutos que como máximo podrá durar el proceso de
búsqueda (sin tener en cuenta el tiempo de procesado). Si no se rellena, su valor
será de 1 minuto por defecto.
• Límite tweets: Número máximo de tweets que se podrán recuperar en la búsqueda.
Si no se rellena, su valor será de 100 tweets por defecto.
Sobre los campos de fecha, sólo se permitirá la búsqueda si los dos campos de
fecha están rellenos, o si los dos están vacíos. En cualquier otro caso la aplicación generará
un mensaje de aviso.
144
10.6.2.4 Panel Geolocalización
Consta de los campos necesarios para geolocalizar lugares (Figura 108).
Figura 108: Panel de Geolocalización
Fuente: Elaboración propia
Si al desplegarse el panel, estaba informado el campo de localización del panel de
Opciones de Búsqueda, se cargará en el mapa su localización, se calcularán las
coordenadas y se obtendrá el nombre que Google Maps tiene asociado a esa posición.
Permite las siguientes operaciones:
• Selección en mapa: El mapa ofrece controles para ampliar/reducir escala y para
moverse a través de él. Pulsando en cualquier punto se cargará la información de
localización en los campos Localización, Latitud y Longitud.
• Calculo de Latitud y Longitud (en grados decimales) a partir del valor rellenado en
el campo de Localización: Rellenar el campo de Localización y pulsar el botón
Buscar localización (Figura 109). Esperar unos segundos para que Google Maps
devuelva la información.
Figura 109: Botón Buscar localización
Fuente: Elaboración propia
• Calculo de Localización a partir de los valores (en grados decimales) rellenados en
los campos de Latitud y Longitud: Rellenar los campos de coordenadas y pulsar
145
uno de los dos botones de Buscar coordenadas (Figura 110). Esperar unos
segundos para que Google Maps devuelva la información.
Figura 110: Botón Buscar coordenadas
Fuente: Elaboración propia
• Limpiar configuración: Pulsar el botón Limpiar configuración geolocalización para
limpiar toda la información de geolocalización del panel (Figura 111).
Figura 111: Botón Limpiar configuración geolocalización
Fuente: Elaboración propia
• Aceptar configuración: Pulsar el botón Aceptar configuración geolocalización para
volver al panel de opciones con la configuración de geolocalización seleccionada.
Es obligatorio que los campos de información estén rellenos (Figura 112).
Figura 112: Botón Aceptar configuración de geolocalización
Fuente: Elaboración propia
• Cancelar configuración: Pulsar en el botón Cancelar configuración geolocalización
para descartar los cambios realizados y devolver el control al panel de opciones de
búsqueda con la información que hubiera informada previamente (Figura 113).
Figura 113: Botón Cancelar configuración de geolocalización
Fuente: Elaboración propia
10.6.2.5 Botones generales
146
• Botón Ejecutar Búsqueda: Ejecuta una búsqueda aplicando las opciones
configuradas. Los tweets obtenidos se almacenarán en la base de datos, en una
colección cuyo nombre será el nombre que se haya rellenado en el campo Nombre
del panel Tema / Dominio (Figura 114).
Figura 114: Botón Ejecutar búsqueda
Fuente: Elaboración propia
• Botón Limpiar Opciones de Búsqueda: Limpia la información del panel Opciones de
Búsqueda (Figura 115).
Figura 115: Botón Limpiar Opciones de Búsqueda
Fuente: Elaboración propia
10.6.3 Interfaz de Visualización
Permite la visualización de estadísticas de las colecciones almacenadas en la base
de datos (Figura 116).
147
Figura 116: Interfaz de Visualización
Fuente: Elaboración propia
Contiene los siguientes paneles y controles:
• Botón Refrescar información: Carga en la interfaz la información existente en la
base de datos (Figura 117).
Figura 117: Botón Refrescar información
Fuente: Elaboración propia
• Estadísticas Globales (Figura 118): Ofrece la volumetría total de tweets en la base
de datos.
148
Figura 118: Panel Estadísticas Globales
Fuente: Elaboración propia
• Estadísticas Colección (Figura 119): Por cada colección existente en la base de
datos se generará un panel que incluirá la información referente al total de tweets
de la colección, total de tweets por idioma y total de tweets por localización.
Figura 119: Panel Estadísticas Colección
Fuente: Elaboración propia
10.6.4 Interfaz de Gestión
149
Permite la eliminación de colecciones (Figura 120).
Figura 120: Interfaz de Gestión
Fuente: Elaboración propia
Contiene los siguientes paneles y controles.
10.6.4.1 Panel Dominios
Contiene una tabla en la que se cargarán los dominios existentes en la base de
datos (Figura120), permitiendo la selección de cada uno de ellos para su eliminación.
10.6.4.2 Botones Generales
• Botón Refrescar información: Carga en la interfaz la información existente en la
base de datos (Figura 121).
Figura 121: Botón Refrescar información
Fuente: Elaboración propia
150
• Botón Eliminar dominios: Elimina los dominios seleccionados de la tabla del panel
Dominios (Figura 122).
Figura 122: Botón Eliminar dominios
Fuente: Elaboración propia
10.6.5 Interfaz de Exportación
Permite la exportación de tweets a ficheros (Figura 123).
Figura 123: Interfaz de Exportación
Fuente: Elaboración propia
Contiene los siguientes paneles y controles:
10.6.5.1 Panel Filtrado de datos
Contiene controles y campos para filtrar y calcular la volumetría de información a
exportar (Figura 124).
151
Figura 124: Panel Filtrado de Datos
Fuente: Elaboración propia
Consta de los siguientes controles y campos:
• Dominios: Permite incluir un listado de nombres de colecciones existentes en base
de datos separadas por “,”. Si el campo no es rellenado la ejecución afectará a toda
la base de datos.
• Localización: Nombre de una localización.
• Fecha inicio: Pulsar en su icono para desplegar un calendario y seleccionar una
fecha de inicio. Los tweets buscados serán los que tengan fecha de creación
superior a la seleccionada.
• Fecha fin: Pulsar en su icono para desplegar un calendario y seleccionar una fecha
de fin. Los tweets buscados serán los que tengan fecha de creación inferior a la
seleccionada.
• Botón Limpiar filtros (Figura 125): Limpia los campos de filtros.
152
Figura 125: Botón Limpiar filtros
Fuente: Elaboración propia
• Botón Calcular estadísticas (Figura 126): Calcula las estadísticas de la base de
datos aplicando los filtros seleccionados. Los resultados serán cargados en los
apartados de Datos y Estadística Descarga.
Figura 126: Botón Calcular estadísticas
Fuente: Elaboración propia
10.6.5.2 Panel Selección de campos
Permite activar/desactivar la selección de los campos que se incluirán en el fichero
de exportación (Figura 127).
Figura 127: Panel Selección de Campos
Fuente: Elaboración propia
La activación/desactivación se puede realizar campo a campo usando su propio
control (Figura 128), o de forma masiva usando los botones Activar todos y Desactivar
todos (Figura 129).
153
Figura 128: Botón Control de selección de campo
Fuente: Elaboración propia
Figura 129: Botones de activación/desactivación masiva
Fuente: Elaboración propia
10.6.5.3 Panel Formato descarga
Permite seleccionar el formato del fichero de descarga entre TXT o CSV (Figura
130).
Figura 130: Panel Formato descarga
Fuente: Elaboración propia
10.6.5.4 Botones generales
• Botón Limpiar opciones de exportación: Limpia todas las opciones de la interfaz
(Figura 131).
Figura 131: Botón Limpiar opciones de exportación
Fuente: Elaboración propia
• Botón Exportar tweets: Exporta a fichero los tweets seleccionados con los campos
y formato seleccionados (Figura 132).
154
Figura 132: Botón Exportar tweets
Fuente: Elaboración propia
Desde el navegador se mostrará un mensaje con el fichero a descargar
(Figura 133). Se deberá seleccionar la opción Guardar archivo para, posteriormente
indicar la ubicación y el nombre del fichero de descarga. Por defecto, el nombre del
fichero estará formado por la fecha de ejecución.
Figura 133: Mensaje de confimación descarga de fichero
Fuente: Elaboración propia
10.7 Manual de instalación
A continuación se describirán los pasos necesarios para la instalación de la
herramienta desarrollada en este trabajo.
10.7.1 Contenido del entregable
La parte software de este trabajo se entrega contenida en la carpeta Recotweets
(Figura 134).
155
Figura 134: Contenido entregable aplicación
Fuente: Elaboración propia
A continuación se describe su contenido:
• Carpeta apache: Contiene el fichero que define los hosts virtuales en Apache2
necesarios para la comunicación con Django (Figura 135).
Figura 135: Fuentes apache
Fuente: Elaboración propia
• Carpeta recotweets: Contiene los fuentes de la aplicación (frontend y backed)
(Figura 136).
156
Figura 136: Fuentes recotweets
Fuente: Elaboración propia
• Carpeta tfg: Contiene ficheros configuración para la gestión del proyecto Django
necesarios para la comunicación con Apache2 (hosts permitidos, definición de urls,
dominios, comunicación con Apache para la ejecución de procesos Python, etc)
(Figura 137).
Figura 137: Fuentes tfg
Fuente: Elaboración propia
157
• manage.py: Fichero gestor del proyecto Django. Es el que indica a Django en qué
fichero puede leer la configuración del proyecto.
10.7.2 Requisitos mínimos
Como requisitos previos, se recomienda que el equipo sobre el que se instale la
herramienta tenga, como mínimo, las siguientes características:
• CPU: ProcesadorIntel(R) Core(TM) i5 CPU M450 @ 2.40GH
• Espacio libre en disco duro: 20 GB.
• Memoria RAM: 4GB.
• Sistema Operativo: Ubuntu 16.04.2 LTS.
• El webdriver para realizar tareas de scraping se ha configurado para simular la
instancia de un navegador Mozilla Firefox, por lo que es requisito indispensable el
uso de la presente herramienta con un navegador Mozilla Firefox.
10.7.3 Instalación de dependencias
A continuación se describe la instalación de componentes externos a la
herramienta, y que son necesarios para su funcionamiento.
10.7.3.1 Python 2.7.13
Recientemente Python ha liberado la versión 2.7.14, por lo que es posible que si se
instala Python mediante la instrucción:
sudo apt-get install python2.7
la versión instalada sea esta última. Para solucionarlo, se indica una instalación alternativa
a través de la ejecución de las instrucciones indicadas en los siguientes pasos.
• Instalación de requisitos previos:
Ejecutar las siguientes instrucciones desde la consola:
$ sudo apt-get update
158
$ sudo apt-get install build-essential checkinstall
$ sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-
dev tk-dev libgdbm-dev libc6-dev libbz2-dev
� Descarga de versión:
$ cd /usr/src
$ wget https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tgz
$ tar xzf Python-2.7.13.tg
$ cd Python-2.7.13
� Compilación:
$ sudo ./configure
$ sudo make altinstall
� Comprobación:
python2.7 -V
El resultado de la instrucción debería ser la versión Python 2.7.13 (Figura
138).
Figura 138: Instalación Python
Fuente: Elaboración propia
• Instalación de librerías genéricas recomendadas:
sudo apt-get update
sudo apt-get install libxml2-dev libxslt1-dev python-dev
sudo apt-get install python-pip
10.7.3.2 MongoDB
159
Para la instalación del servidor de base de datos MongoDB es necesario seguir los
siguientes pasos:
• Obtener la clave de acceso al repositorio oficial de MongoDB:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
• Generación de fichero con la URL al repositorio de MongoDB:
echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.2 multiverse"
| sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list
• Instalación de MongoDB:
sudo apt-get update
sudo apt-get install -y mongodb-org
• Comprobar instalación:
mongo –version
La versión que debería aparecer es una release de la 3.2 (Figura 139)
Figura 139: Instalación MongoDB (I)
Fuente: Elaboración propia
• Configuar MongoDB como un servicio de Ubuntu 16.04. Para ello crear el fichero
mongodb.service mediante la ejecución de la instrucción:
sudo nano /etc/systemd/system/mongodb.service
Una vez abierto, incluir dentro de él las siguientes instrucciones:
[Unit]
160
Description=High-performance, schema-free document-oriented database
After=network.target
[Service]
User=mongodb
ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf
[Install]
WantedBy=multi-user.target
• Arrancar el nuevo servicio:
sudo systemctl start mongodb
• Comprobar que ha arrancado correctamente (Figura 140):
sudo systemctl status mongodb
Figura 140: Instalación MongoDB (II)
Fuente: Elaboración propia
• Habilitar el arranque automático de MongoDB al arrancar el sistema:
sudo systemctl enable mongodb
• Configuración de Usuarios: Ejecutar en la consola las siguientes instrucciones:
� Acceso a la consola de MongoDB: mongo
� Crear super usuario administrador:
161
use admin
db.createUser({user:'recotweets', pwd:'pass', roles:
['userAdminAnyDatabase','readWriteAnyDatabase']})
� Salir de MongoDB y acceder con superusuario:
mongo admin -u recotweets -p
� Crear usuarios con permisos de lectura y escritura solo de una base de
datos específica. Estos usuarios serán los usados por la aplicación para
acceder a las bases de datos de tweets y de usuarios:
db.createUser({user:'tfg', pwd:'pass',roles: [{role:'readWrite', db:'tweets'}]})
db.createUser({user:'tfguser', pwd:'pass',roles: [{role:'readWrite',
db:'usuarios_rec'}]})
� Salir de MongoDB y acceder con el nuevo usuario tfg para crear la base de
datos tweets:
mongo -u tfg -p pass
use tweets
� Salir de MongoDB y acceder con el nuevo usuario usuarios_rec para crear
la base de datos usuarios:
mongo -u usuarios_rec -p pass
use usuarios
� Comprobación de bases de datos creadas (Figura 141):
mongo admin -u joaquin -p pass
show databases
162
Figura 141: Instalación MongoDB (III)
Fuente: Elaboración propia
10.7.3.3 PyMongo
Driver oficial de Python para MongoDB. Para instalarlo, ejecutar las siguientes
instrucciones en la consola:
sudo apt-get update
sudo apt-get install python-pymongo
10.7.3.4 Dateutil
Librería que amplía funcionalidades del módulo datetime en el tratamiento de
fechas. Para instalarlo, ejecutar las siguientes instrucciones en la consola:
sudo apt-get update
sudo apt-get install python-dateutil
10.7.3.5 Tweepy
Librería para gestionar la comunicación con la Straming API de Twitter. Para
instalarla ejecutar en la consola:
sudo apt-get update
sudo apt-get install python-tweepy
10.7.3.6 BeautifulSoup4
Permite extraer datos de páginas HTML de forma sencilla realizando un rastreo del
árbol DOM. Para instalarla ejecutar en la consola:
163
sudo apt-get update
sudo apt-get install python-bs4
10.7.3.7 Selenium
Librería para la emulación de la navegación desde el propio navegador Para
instalarla ejecuta en la consola:
sudo pip install selenium
10.7.3.8 PhantomJS
WebDriver para Selenium, permite emular el comportamiento del navegador sin
levantar una instancia. Para instalarlo ejecutar en la consola:
sudo apt-get install phantomjs
10.7.3.9 Geopy
Librería para realizar peticiones de geolocalización a servidor geocoder. Para
instalara ejecutar en la consola:
sudo apt-get update
sudo apt-get install python-geopy
10.7.3.10 Dataparser
Librería para parsear a formato datetime fechas descritas en lenguage natural
usadas por BAT. Para instalarlo ejecutar en la consola:
sudo pip install dateparser
10.7.3.11 Apache2
Servidor web para gestionar las peticiones entre cliente y Django. Para instalarlo
ejecutar las siguientes instrucciones:
164
sudo apt-get update
sudo apt-get install apache2
• Instalación del fichero de virtualhost en Apache: Depositar fichero recotweets.conf,
contenido en la carpeta de entregra Recotweets/apache en la ruta:
/etc/apache2/sites-available
• Activar el host virtual:
sudo a2ensite recotweets
• Modificar el fichero de configuración de Apache2 (/etc/apache2/apache2.conf) y
añadir las siguientes directivas para que, cuando se descargue desde la aplicación
un fichero de tweets con formato txt, el navegador muestre un menú de descarga
en lugar de abrirlo directamente:
<FilesMatch ".(csv|txt)$" >
ForceType application/octet-stream
Header add Content-Disposition "attachment"
</FilesMatch>
• Activar módulo para modificar cabeceras HTTP:
sudo a2enmod headers
sudo apachectl -t
sudo /etc/init.d/apache2 restart
• Instalar el cerfificado digital autofirmado de acuerdo con lo comentado en el
apartado 10.4 Generación de certificado SSL con autofirma y activar el módulo SSL
de Apache:
sudo a2enmod ssl
sudo /etc/init.d/apache2 restart
165
10.7.3.12 Django
Framework de Python. Para instalarlo, ejecutar las siguientes instrucciones:
sudo apt-get update
sudo apt-get install python-django
Comprobar que es accesible desde Python (Figura 142). Para ello acceder a la
consola de Python mediante la instrucción
python
Y ejecutar
import django
print(django.get_version())
Figura 142: Comprobación acceso a Django desde Python
Fuente: Elaboración propia
10.7.3.13 Módulo WSGI
Estándar de comunicación entre servidor web y módulos de Phyton. Para instalarlo
ejecutar las siguientes instrucciones:
sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install apache2 apache2-utils libexpat1 ssl-cert
sudo apt-get update
sudo apt-get install libapache2-mod-wsgi
166
Activar módulo wsgi (para usar con django):
sudo a2enmod wsgi
sudo /etc/init.d/apache2 restart
10.7.4 Instalación de fuentes
A continuación se describen los pasos necesarios para instalación de los fuentes.
10.7.4.1 Creación de proyecto Django
Como paso previo a la instalación de los fuentes, es necesaria la creación de un
proyecto Django desde el que se gestionarán todas las peticiones. Para ello seguir los
siguientes pasos:
• Crear ruta contenedora /home/proyecto_tfg:
mkdir /home/proyecto_tfg
chmod 775 /home/proyecto_tfg
cd /home/proyecto_tfg
• Crear proyecto dentro de esta ruta:
djangoadmin startproject proyecto_django
• Comprobar que se ha creado la ruta /home/proyecto_tfg/proyecto_django (Figura
143).
Figura 143 : Creación proyecto Django
Fuente: Elaboración propia
Si la ruta creada no tiene permisos 775, asignárselos:
chmod 775 /home/proyecto_tfg/proyecto_django
167
• Crear aplicación en el proyecto Django para alojar los fuentes:
python manage.py startapp recotweets
Comprobar que se ha creado la ruta (Figura 144)
/home/proyecto_tfg/proyecto_django/recotweets/
Figura 144 Aplicación Django
Fuente: Elaboración propia
Si la ruta creada no tiene permisos 775, asignárselos:
chmod 775 /home/proyecto_tfg/proyecto_django
/home/proyecto_tfg/proyecto_django/recotweets
10.7.4.2 Insalación de fuentes
Para la insalación de fuentes seguir los siguientes pasos:
• Instalación de fichero gestor del proyecto Django:
� Depositar el fuente manage.py contenido en la carpeta de entrega
Recotweets, en la ruta
/home/proyecto_tfg/proyecto_django/
• Instalación de fuentes de configuración de proyecto Django:
� Modificar en el fichero de entrega Recotweets/tfg/settings.py el valor de la
clave de producto de Django SECRET_KEY por el valor que tiene
configurado el fichero
/home/proyecto_tfg/proyecto_django/tfg/settings.py
168
� Depositar los fuentes contenidos en la carpeta tfg incluida dentro de la
carpeta de entrega Recotweets, en la ruta
/home/proyecto_tfg/proyecto_django/tfg
sobreescribiendo todos los ficheros.
� Instalación de fuentes de aplicación:
� Crear directorios:
mkdir /home/proyecto_tfg/proyecto_django/recotweets/log
mkdir /home/proyecto_tfg/proyecto_django/recotweets/static/desc/
� Depositar los fuentes contenidos en la carpeta recotweets incluida
dentro de la carpeta de entrega Recotweets, manteniendo la misma
estructura de directorios de la capeta de entrega, en la ruta
/home/proyecto_tfg/proyecto_django/recotweets
sobreescribiendo todos los ficheros.
� Asignar los siguientes permisos:
chmod 775 /home/proyecto_tfg/proyecto_django/recotweets/script
chmod 775 /home/proyecto_tfg/proyecto_django/recotweets/config
chmod 775 /home/proyecto_tfg/proyecto_django/recotweets/static
chmod 777 /home/proyecto_tfg/proyecto_django/recotweets/log
chmod 755 /home/proyecto_tfg/proyecto_django/recotweets/lanzador_sapache2.sh
chmod 755 /home/proyecto_tfg/proyecto_django/recotweets/lanzador_smongodb.sh
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/log.py
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/api_recotweets.py
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/mitest.py
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/api_scraping.py
chmod 777 /home/proyecto_tfg/proyecto_django/recotweets/api_bd.py
chmod 777 /home/proyecto_tfg/proyecto_django/recotweets/api_twitter.py
chmod 777 /home/proyecto_tfg/proyecto_django/recotweets/useragent.properties
169
chmod 777 /home/proyecto_tfg/proyecto_django/recotweets/peticion.properties
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/script/sbdstart.py
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/script/sbdstop.py
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/script/swebstart.py
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/script/swebstop.py
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/script/swebrestart.py
chmod 777 /home/proyecto_tfg/proyecto_django/recotweets/static/index.html
chmod 755 /home/proyecto_tfg/proyecto_django/recotweets/static/images/
chmod 755 /home/proyecto_tfg/proyecto_django/recotweets/static/js/
chmod 755 /home/proyecto_tfg/proyecto_django/recotweets/static/css/
chmod 755 /home/proyecto_tfg/proyecto_django/recotweets/static/fonts/
chmdo 777 /home/proyecto_tfg/proyecto_django/recotweets/static/desc/
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/static/images/*
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/static/js/*
chmod 664 /home/proyecto_tfg/proyecto_django/recotweets/static/css/*
� Modificar el fichero
/home/proyecto_tfg/proyecto_django/tfg/settings.py
para añadir en el listado de hosts permitidos ALLOWED_HOSTS, la
IP de la máquina en la que haya sido instalado el servidor, y el
dominio recotweets.com, para que quede de la siguiente manera:
ALLOWED_HOSTS = ['localhost', '127.0.0.1', IP_SERVIDOR, DOMINIO]
10.7.4.3 Configuración para ejecutar en la misma máquina
Dado que durante el desarrollo servidor y cliente están alojados en la misma
máquina, y no se posee un dominio en propiedad, se han modificado los siguientes
ficheros:
• Fichero de hosts de la máquina (/etc/hosts): Añadir el dominio recotweets.com y la
IP local que es la dirección del servidor
• Fichero de configuración del proyecto Django
/home/proyecto_tfg/proyecto_django/tfg/settings.py
170
para añadir en la lista de hosts permitidos ALLOWED_HOSTS el dominio
recotweets.com.
10.7.5 Arranque de servidores
Una vez instalados los fuentes, antes de comenzar a utilizar la aplicación es
necesario arrancar los servidores de Apache2 y MongoDB. Para ello ejecutar en la consola
las siguientes instrucciones:
cd /home/proyecto_tfg/proyecto_django/recotweets/
sudo ./lanzador_smongodb.sh start
sudo ./lanzador_sapache2.sh restart
Se puede comprobar el estado de los servidores revisando los siguientes logs de
arranque:
/home/proyecto_tfg/proyecto_django/recotweets/script/estado_sbd.log
/home/proyecto_tfg/proyecto_django/recotweets/script/estado_sweb.log
171
11 REFERENCIAS BIBLIOGRÁFICAS
[1] VÁSQUEZ, Augusto Cortez, et al. Procesamiento de lenguaje natural. Revista de
investigación de Sistemas e Informática, 2009, vol. 6, no 2, p. 45-54.
[2] Web 2.0. Wikipedia [consulta: 8 marzo 2017]. Disponible en:
https://es.wikipedia.org/wiki/Web_2.0
[3] Informe Mobile en España y en el Mundo 2017. Ditrendia [consulta: 9 marzo 2017].
Disponible en: http://www.amic.media/media/files/file_352_1289.pdf
[4] CÁMARA, Eugenio Martinez; VALDIVIA, MaTeresa Martin; URENA, L. Alfonso. Análisis
de Sentimientos. IV Jornadas TIMM Tratamiento de la Información Multilingüe y Multimodal
7 y 8 de abril de 2011, 2011, p. 61.
[5] Twitter. Twitter [consulta: 8 marzo 2017]. Disponible en: https://twitter.com/
[6] MARTÍNEZ-CÁMARA, Eugenio, et al. Sentiment analysis in Twitter. Natural Language
Engineering, 2014, vol. 20, no 1, p. 1-28.
[7] Twitter. Wikipedia [consulta: 8 marzo 2017]. Disponible en:
https://es.wikipedia.org/wiki/Twitter
[8] Twitter Usage Statistics. InternetLiveStats [consulta: 10 marzo 2017]. Disponible en:
http://www.internetlivestats.com/twitter-statistics/
[9] AHMED, Wasim. Using Twitter as a data source: an overview of social media research
tools (updated for 2017). Impact of Social Sciences Blog, 2017.
[10] NodeXL. Social Media Research Foundation [consulta: 13 marzo 2017]. Disponible en:
http://www.smrfoundation.org/
[11] DiscoverTex. Texifter [consulta: 14 marzo 2017]. Disponible en:
https://discovertext.com/
172
[12] SurveyMonkey. SurveyMonkey [consulta: 14 marzo 2017]. Disponible en:
https://es.surveymonkey.com/
[13] Building the Future of the Twitter API Platform. Developer Blog [consulta: 06 abril 2017].
Disponible en: https://blog.twitter.com/developer/en_us/topics/tools/2017/building-the-
future-of-the-twitter-api-platform.html
[14] Twitter Developer Platform Roadmap. Trello [consulta: 06 abril 2017]. Disponible en:
https://trello.com/b/myf7rKwV/twitter-developer-platform-roadmap
[15] Refreshing and bringing together our developer resources. Developer Blog [consulta:
25 septiembre 2017]. Disponible en:
https://blog.twitter.com/developer/en_us/topics/tools/2017/refreshing-and-bringing-
together-our-developer-resources.html
[16] JSON. Wikipedia [consulta: 8 marzo 2017]. Disponible en:
https://es.wikipedia.org/wiki/JSON
[17] Docs. Twitter Developers [consulta: 8 marzo 2017]. Disponible en:
https://dev.twitter.com/docs
[18] Things every developer should know. Twitter Developers [consulta: 10 marzo 2017].
Disponible en: https://dev.twitter.com/basics/things-every-developer-should-know
[19] API. Twitter Developers [consulta: 10 marzo 2017]. Disponible en:
https://dev.twitter.com/overview/api
[20] Authentication. Twitter Developers [consulta: 10 marzo 2017]. Disponible en:
https://dev.twitter.com/oauth/overview/authentication-by-api-family
[21] Twitter Libraries. Twitter Developers [consulta: 10 marzo 2017]. Disponible en:
https://dev.twitter.com/resources/twitter-libraries
[22] REST API. Twitter Developers [consulta: 11 marzo 2017]. Disponible en:
https://dev.twitter.com/rest/public
173
[23] Rate Limiting. Twitter Developers [consulta: 11 marzo 2017]. Disponible en:
https://dev.twitter.com/rest/public/rate-limiting
[24] Search API. Twitter Developers [consulta: 11 marzo 2017]. Disponible en:
https://dev.twitter.com/rest/public/search
[25] List of ISO 639-1 codes. Wikipedia [consulta: 13 marzo 2017]. Disponible en:
https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
[26] Streaming API. Twitter Developers [consulta: 13 marzo 2017]. Disponible en:
https://dev.twitter.com/streaming/overview
[27] POST statuses/filter. Twitter Developers [consulta: 14 marzo 2017]. Disponible en:
https://dev.twitter.com/streaming/reference/post/statuses/filter
[28] Anexo:Códigos de estado HTTP. Wikipedia [consulta: 11 marzo 2017]. Disponible en:
https://es.wikipedia.org/wiki/Anexo:C%C3%B3digos_de_estado_HTTP
[29] GNIP. Twitter Developers [consulta: 15 marzo 2017]. Disponible en: https://gnip.com/
[30] Building the Future of the Twitter API Platform. Twitter Developer Blog [consulta: 06
abril 2017]. Disponible en:
https://blog.twitter.com/developer/en_us/topics/tools/2017/building-the-future-of-the-
twitter-api-platform.html
[31] Búsqueda avanzada. Twitter [consulta: 17 marzo 2017]. Disponible en:
https://twitter.com/search-advanced?lang=es
[32] Web scraping. Wikipedia [consulta: 17 marzo 2017]. Disponible en:
https://es.wikipedia.org/wiki/Web_scraping
[33] RAULAMO-JURVANEN, Päivi; KAKKONEN, Kari; MÄNTYLÄ, Mika. Using Surveys
and Web-Scraping to Select Tools for Software Testing Consultancy. En Product-Focused
Software Process Improvement: 17th International Conference, PROFES 2016, Trondheim,
Norway, November 22-24, 2016, Proceedings 17. Springer International Publishing, 2016.
p. 285-300.
174
[34] Tweets. Twitter Developers [consulta: 23 marzo 2017]. Disponible en:
https://dev.twitter.com/overview/api/tweets
[35] Upcoming changes to Tweets. Twitter Developers [consulta: 30 marzo 2017].
Disponible en: https://dev.twitter.com/overview/api/upcoming-changes-to-tweets
[36] TORRECILLA SALINAS, Carlos Joaquín. A mature agile approach in web engineering
contexts. 2017.
[37] CABELLO, Antonio Luis Cardador. Implantación de aplicaciones web en entornos
internet, intranet y extranet. IFCD0210. IC Editorial, 2015.
[38] Programación por capas. Wikipedia [consulta: 06 abril 2017]. Disponible en:
https://es.wikipedia.org/wiki/Programaci%C3%B3n_por_capas
[39] MVC. Information Technology Consulting [consulta: 06 abril 2017]. Disponible en:
http://www.itc-software.com.ar/Newsletter/024/Newsletter_201410.html
[40] BEATI, Hernán. HTML5 y CSS3-Para diseñadores. Alfaomega Grupo Editor, 2016.
[41] CSS3. MDN web docs [consulta: 06 abril 2017]. Disponible en:
https://developer.mozilla.org/es/docs/Web/CSS/CSS3
[42] JavaScript. MDN web docs [consulta: 06 abril 2017]. Disponible en:
https://developer.mozilla.org/es/docs/Web/JavaScript
[43] jQuery. The jQuery Foundation [consulta: 06 abril 2017]. Disponible en:
https://jquery.com/
[44] AngularJS. AngularJS [consulta: 06 abril 2017]. Disponible en: https://angularjs.org/
[45] BackBone.js. BackBone.js [consulta: 06 abril 2017]. Disponible en:
http://backbonejs.org/
[46] Ember.js. Tilde Inc [consulta: 07 abril 2017]. Disponible en: https://www.emberjs.com/
[47] React. Facebook Inc [consulta: 07 abril 2017]. Disponible en: https://reactjs.org/
175
[48] Bootstrap. Bootstrap [consulta: 07 abril 2017]. Disponible en: http://getbootstrap.com/
[49] Node.js. Node.js [consulta: 07 abril 2017]. Disponible en: https://nodejs.org/es/
[50] Java (lenguaje de programación). Wikipedia [consulta: 08 abril 2017]. Disponible en:
https://es.wikipedia.org/wiki/Java_(lenguaje_de_programaci%C3%B3n)
[51] Spring. Pivotal Softwate [consulta: 08 abril 2017]. Disponible en: https://spring.io/
[52] Hibernate. Red Hat [consulta: 08 abril 2017]. Disponible en: https://spring.io/
[53] PHP. Wikipedia [consulta: 09 abril 2017]. Disponible en:
https://es.wikipedia.org/wiki/PHP
[54] Laravel. Laravel [consulta: 09 abril 2017]. Disponible en: https://laravel.com/
[55] symfony.es. symfony.es [consulta: 09 abril 2017]. Disponible en: https://laravel.com/
[56] Python. Python [consulta: 09 abril 2017]. Disponible en: https://www.python.org/
[57] Django. Django [consulta: 09 abril 2017]. Disponible en:
https://www.djangoproject.com/
[57] Web2py. Web2py [consulta: 09 abril 2017]. Disponible en:
https://www.djangoproject.com/
[59] Pyramid. Pylons Project [consulta: 09 abril 2017]. Disponible en:
https://www.djangoproject.com/
[60] Understanding SQL And NoSQL Databases And Different Database Models.
DigitalOcean [consulta: 10 abril 2017]. Disponible en:
https://www.digitalocean.com/community/tutorials/understanding-sql-and-nosql-
databases-and-different-database-models
[61] ¿Qué es una Base de Datos NoSQL? Oracle [consulta: 10 abril 2017]. Disponible en:
https://blogs.oracle.com/uncafeconoracle/qu-es-una-base-de-datos-nosql
176
[62] DB-Engines Ranking. DB-Engines [consulta: 10 abril 2017]. Disponible en: https://db-
engines.com/en/ranking
[63] Drivers. MongoDB [consulta: 10 abril 2017]. Disponible en:
https://docs.mongodb.com/getting-started/shell/drivers/
[64] AJAX. Wikipedia [consulta: 11 abril 2017]. Disponible en:
https://es.wikipedia.org/wiki/AJAX
[65] Servicios web RESTful con HTTP. Parte I: Introducción y bases téoricas. ADWE
[consulta: 11 abril 2017]. Disponible en:
http://www.adwe.es/general/colaboraciones/servicios-web-restful-con-http-parte-i-
introduccion-y-bases-teoricas
[66] Mongoengine is very slow on large documents comapred to native pymongo usage.
Stack Overflow [consulta: 11 abril 2017]. Disponible en:
https://stackoverflow.com/questions/35257305/mongoengine-is-very-slow-on-large-
documents-comapred-to-native-pymongo-usage
[67] Beautiful Soup Documentation. Crummy [consulta: 12 abril 2017]. Disponible en:
https://www.crummy.com/software/BeautifulSoup/bs4/doc/#
[68] Scrapy. Scrapinghub [consulta: 12 abril 2017]. Disponible en: https://scrapy.org/
[69] Selenium. SeleniumHQ [consulta: 12 abril 2017]. Disponible en:
http://www.seleniumhq.org/
[70] Comparativa entre los principales servidores web. Bitendian [consulta: 12 abril 2017].
Disponible en: http://www.bitendian.com/es/comparativa-entre-los-principales-servidores-
web/
[71] Web Server Gateway Interface. Wikipedia [consulta: 12 abril 2017]. Disponible en:
https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface
[72] Web Server Gateway Interface. Twitter Developers [consulta: 13 julio 2017]. Disponible
en: https://twittercommunity.com/t/4-options-for-web-scraping-twitter/71535
177
[73] BSON Types. MongoDB [consulta: 4 abril 2017]. Disponible en:
https://docs.mongodb.com/manual/reference/bson-types/
[74] MockFlow. MockFlow [consulta: 17 abril 2017]. Disponible en:
https://mockflow.com/index.jsp
[75] Google Maps API. Google [consulta: 21 julio 2017]. Disponible en:
https://developers.google.com/maps/documentation/javascript/get-api-key
[76] Google Maps JavaScript API Límites de uso. Google [consulta: 21 julio 2017].
Disponible en: https://developers.google.com/maps/documentation/javascript/get-api-key
[77] VirtualHost Examples. Apache [consulta: 8 julio 2017]. Disponible en:
http://httpd.apache.org/docs/current/vhosts/examples.html
[78] Same-origin policy. MDN web docs [consulta: 8 julio 2017]. Disponible en:
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
[79] Python Requests: requests.exceptions.TooManyRedirects: Exceeded 30 redirects.
Stack Overflow [consulta: 5 mayo 2017]. Disponible en: https://developer.mozilla.org/en-
US/docs/Web/Security/Same-origin_policy
[80] Nominatim Usage Policy. OSMF Operations Working Group [consulta: 16 junio 2017].
Disponible en: https://operations.osmfoundation.org/policies/nominatim/
[81] Geocodificación de direcciones con Python. Alter Geosistemas [consulta: 16 junio
2017]. Disponible en: https://www.altergeosistemas.com/blog/2015/11/19/geocodificacion-
direcciones-python/
[82] Beautiful Soup Documentation. Crummy [consulta: 16 junio 2017]. Disponible en:
https://www.altergeosistemas.com/blog/2015/11/19/geocodificacion-direcciones-python/
[83] HTMLUnitDriver & PhantomJS for Selenium Headless Testing. Guru99 [consulta: 17
junio 2017]. Disponible en: https://www.guru99.com/selenium-with-htmlunit-driver-
phantomjs.html
178
[84] selenium.webdriver.common.desired_capabilities. SeleniumHQ [consulta: 21 junio
2017]. Disponible en:
https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.
desired_capabilities.html
[85] Frecuencia de aparición de letras. Wikiwand [consulta: 23 junio 2017]. Disponible en:
https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.
desired_capabilities.html
[86] Chart.js. Chartjs [consulta: 25 julio 2017]. Disponible en: http://www.chartjs.org/
[87] Get Twitter supported languages. Twitter Developers [consulta: 4 septiembre 2017].
Disponible en: https://developer.twitter.com/en/docs/developer-utilities/supported-
languages/api-reference/get-help-languages
[88] Response Codes. Twitter Developers [consulta: 11 marzo 2017]. Disponible en:
https://developer.twitter.com/en/docs/basics/response-codes
[89] Filter Realtime Tweets. Twitter Developers [consulta: 13 marzo 2017]. Disponible en:
https://developer.twitter.com/en/docs/tweets/filter-realtime/guides/connecting
[90] Tokens from dev.twitter.com. Twitter Developers [consulta: 17 abril 2017]. Disponible
en: https://dev.twitter.com/oauth/overview/application-owner-access-tokens
[91] Twitter Apps. Twitter [consulta: 17 abril 2017]. Disponible en: https://apps.twitter.com/
[92] Cómo crear un certificado SSL de firma propia con OpenSSL y Apache HTTP Server.
NanoTutoriales [consulta: 7 septiembre 2017]. Disponible en:
https://www.nanotutoriales.com/como-crear-un-certificado-ssl-de-firma-propia-con-
openssl-y-apache-http-server