Esta es la segunda de una serie de dos partes sobre el uso de las redes sociales para localizar testigos oculares de eventos importantes. En la primera parte, te mostré cómo usar la API de Instagram para encontrar testigos presenciales de una sesión de video en vivo de Macklemore's en Seattle. En esta parte, usaremos la API de Twitter para encontrar asistentes al discurso del presidente Obama en Selma en el puente Edmund Pettus.
Puede descargar el código para ambos episodios utilizando el enlace del repositorio de GitHub en la barra lateral. También te puede interesar mi serie Tuts +, Creación con la API de Twitter.
Las capacidades de geosearch de Twitter son más limitadas y, por lo tanto, requieren un código un poco más detallado para su uso. Las publicaciones con etiquetas geográficas en Twitter solo se pueden encontrar en los últimos siete días. Y solo se pueden buscar por fecha (no por hora), por lo que debe filtrar los resultados de la API para obtener precisión.
Yo participo en las discusiones de abajo. Si tiene alguna pregunta o sugerencia sobre un tema, por favor envíe un comentario a continuación. También puedes contactarme en Twitter @reifman o enviarme un correo electrónico directamente.
Los teléfonos que llevamos en nuestros bolsillos registran cada uno de nuestros movimientos, compartiéndolos con proveedores celulares y, a menudo, con compañías de software de terceros cuyas motivaciones generalmente se centran en las ganancias.
Muchas personas no se dan cuenta de que han dejado el etiquetado geográfico en sus aplicaciones de redes sociales, publicando completamente su ubicación con cada publicación en las redes sociales. Esto incluía al congresista republicano Aaron Schock. El AP usó las etiquetas geográficas de su cuenta de Instagram para exponer su uso de los fondos de los contribuyentes para vuelos privados extravagantes y otras actividades de lujo..
Por lo tanto, el etiquetado geográfico se puede utilizar para siempre. En esta serie, estamos explorando cómo los periodistas o las autoridades policiales pueden ubicar a posibles testigos oculares de eventos importantes, como la escena de un crimen o un accidente, utilizando las redes sociales..
Sin embargo, el etiquetado geográfico también se puede utilizar de forma abusiva. Los informáticos y educadores de Berkeley construyeron el ¿Listo o no? Aplicación para mostrar cómo las etiquetas geográficas en Twitter e Instagram registran cada uno de nuestros movimientos..
Aquí está la cuenta de Twitter del cofundador de Apple, Steve Wozniak, en la aplicación:
El etiquetado geográfico en Instagram y Twitter es lo suficientemente preciso para permitir que alguien determine fácilmente su residencia, lugar de trabajo y rutina de viaje..
En este episodio, te guiaré a través del uso de la API de Twitter. He proporcionado un repositorio de GitHub (el enlace se encuentra en la barra lateral) para que lo descargues y pruebes el código. Mi "aplicación Eyewitness" está escrita en Yii Framework for PHP, sobre la que puedes aprender más en mi serie Programming With Yii2 para Tuts+.
Si no desea compartir su ubicación para que el público la vea, o para dejar un rastro histórico de sus viajes, ¿Listo o No? La aplicación ofrece enlaces y guías para desactivar estas funciones (busque el enlace en su página de inicio). Francamente, he apagado el mío y te animo a que lo hagas también.
Si usted es una agencia de cumplimiento de la ley o una entidad de medios de comunicación que desea obtener más información, no dude en comunicarse conmigo directamente. También me interesaría cualquier uso exitoso de este código (para bien); harían una interesante historia de seguimiento.
En el último episodio, usamos la API de Instagram para encontrar testigos presenciales del video de Mackelmore en vivo en 2013 para White Cadillac. Fácilmente, nos las arreglamos para encontrar la foto de Macklemore del miembro de Instagram Joshua Lewis saliendo de su vehículo (genial, ¿eh?):
Ahora, comencemos usando la API de Twitter.
Al igual que con Instagram, debes iniciar sesión en tu cuenta de Twitter y registrar una aplicación de desarrollador. Debes registrar una aplicación como esta:
Twitter te mostrará los detalles de tu aplicación:
Aquí está la página de configuración:
Aquí están las claves y tokens de acceso para la aplicación. Toma nota de estos.
Luego, desplácese hacia abajo y cree tokens de acceso para su cuenta. Toma nota de esto también.
Agregue las cuatro claves y secretos de configuración a su /var/secure/eyew.ini
expediente:
MYSQL_HOST = "localhost" mysql_db = "eyew" mysql_un = "xxxxxxxxx" MYSQL_PWD = "XXXXXXXXXXXX" instagram_client_id = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7" instagram_client_secret = "1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4" twitter_key = "zxxxxxxxxxxxxxxxxxxxx2" twitter_secret = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxp" twitter_oauth_token = "1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxs" twitter_oauth_secret = "exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxV"
Luego, crearemos una migración de Registro Activo para crear nuestro modelo de Twitter. Esto almacenará los tweets que recibimos de las llamadas a la API..
db-> driverName === 'mysql') $ tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'; $ this-> createTable ('% twitter', ['id' => Schema :: TYPE_PK, 'moment_id' => Schema :: TYPE_INTEGER. 'NOT NULL', 'tweet_id' => Schema :: TYPE_BIGINT. 'NOT NULL', 'twitter_id' => Schema :: TYPE_BIGINT. 'NOT NULL', 'screen_name' => Schema :: TYPE_STRING. 'NOT NULL DEFAULT 0', 'text' => Schema :: TYPE_TEXT. ' NOT NULL ',' tweeted_at '=> Schema :: TYPE_INTEGER.' NOT NULL ',' created_at '=> Schema :: TYPE_INTEGER.' NOT NULL ',' updated_at '=> Schema :: TYPE_INTEGER.' NOT NULL ',] , $ tableOptions); $ this-> addForeignKey ('fk_twitter_moment', '% twitter', 'moment_id', '% moment', 'id', 'CASCADE', 'CASCADE'); función pública hacia abajo () $ this-> dropForeignKey ('fk_twitter_moment', '% twitter'); $ this-> dropTable ('% twitter');
Al igual que hicimos en la primera parte, debe ejecutar la migración:
./ yii migrate / up Yii Migration Tool (basada en Yii v2.0.3) Total 1 nueva migración que se aplicará: m150309_174014_create_twitter_table ¿Aplicar la migración anterior? (sí | no) [no]: sí *** aplicando m150309_174014_create_twitter_table> crear tabla % twitter… hecho (tiempo: 0.008s)> agregar clave foránea fk_twitter_moment: % twitter (momento_id) referencias % momento (id)… hecho (tiempo: 0.007s) *** aplicado m150309_174014_create_twitter_table (tiempo: 0.019s) Migrado correctamente.
Luego, utilicé el generador de código de Yii2, Gii, para crear el modelo y los controladores CRUD para el modelo de Twitter. Si obtiene el último código de repositorio de GitHub usando el enlace de la barra lateral en este tutorial, también tendrá el código.
Debido a que Twitter limita las búsquedas de geolocalización a la semana pasada, finalmente elegí el discurso del presidente Obama en el 50 aniversario de Selma en el puente Edmund Pettus.
Usé Google Maps nuevamente para obtener las coordenadas GPS para el puente:
Entonces, creé un momento para buscar el discurso. Lo actualicé varias veces para modificar el radio geográfico de la búsqueda (es un puente) y el rango de tiempo:
Las limitaciones de la API de Twitter son que solo te permite buscar por fecha, por ejemplo. 2015-03-07, mientras que Instagram está indexado por marcas de tiempo precisas de Unix. Por lo tanto, tenemos que comenzar nuestra búsqueda de Twitter un día completo por delante y buscar hacia atrás.
Como es probable que obtengamos muchos tweets fuera de nuestro rango de tiempo deseado, tenemos que hacer llamadas repetidas a la API de Twitter. Twitter devuelve hasta 100 tweets por solicitud de API y permite 180 solicitudes por ventana de 15 minutos.
Estoy usando la biblioteca de la API de Twitter de James Mallison para PHP. Así es como configuramos la biblioteca para hacer llamadas:
\ Yii :: $ app-> params ['twitter'] ['oauth_token'], 'oauth_access_token_secret' => \ Yii :: $ app-> params ['twitter'] ['oauth_secret'], 'consumer_key' => \ Yii :: $ app-> params ['twitter'] ['key'], 'consumer_secret' => \ Yii :: $ app-> params ['twitter'] ['secret'],); // Conectarse a Twitter $ twitter = nuevo TwitterAPIExchange ($ settings);
Inicialmente, solicitamos 100 resultados de Twitter en nuestras coordenadas GPS hasta una fecha específica.
función pública searchTwitter () date_default_timezone_set ('America / Los_Angeles'); Yii :: trace ('start searchTwitter' .date ('y-m-d h: m')); // Cargar las claves de la aplicación de Twitter $ settings = array ('oauth_access_token' => \ Yii :: $ app-> params ['twitter'] ['oauth_token'], 'oauth_access_token_secret' => \ Yii :: $ app-> params ['twitter'] ['oauth_secret'], 'consumer_key' => \ Yii :: $ app-> params ['twitter'] ['key'], 'consumer_secret' => \ Yii :: $ app-> params ['twitter'] ['secret'],); // Conectarse a Twitter $ twitter = nuevo TwitterAPIExchange ($ settings); // Configuración de consulta para la búsqueda $ url = 'https://api.twitter.com/1.1/search/tweets.json'; $ requestMethod = 'GET'; // límite de tasa de 180 consultas $ límite = 180; $ query_count = 1; $ cuenta = 100; $ result_type = 'recent'; // calcular el intervalo de marca de tiempo válido $ valid_start = $ this-> start_at; // $ until_date y $ valid_end = // hora de inicio + duración $ valid_end = $ this-> start_at + ($ this-> duration * 60); Yii :: trace ('Rango válido:'. $ Valid_start. '->'. $ Valid_end); $ until_date = date ('Y-m-d', $ valid_end + (24 * 3600)); // agregar un día $ distance_km = $ this-> distance / 1000; // distancia en km // Sin usar: & since = $ since_date // $ since_date = '2015-03-05'; // Realice la primera consulta con until_date $ getfield = "? Result_type = $ result_type & geocode =". $ This-> latitude. ",". $ This-> longitude. ",". $ Distance_km. "Mi & include_entities = false & until = $ until_date & count = $ count ";
Solo registramos tweets dentro de nuestro rango de tiempo preciso, ignorando los otros resultados. Mientras procesamos esto, tomamos nota de la ID de tweet más baja recibida.
$ tweets = json_decode ($ twitter-> setGetfield ($ getfield) -> buildOauth ($ url, $ requestMethod) -> performRequest ()); if (isset ($ tweets-> errores)) Yii :: $ app-> session-> setFlash ('error', 'Twitter Rate Limit Reached.'); Yii :: error ($ tweets-> errores [0] -> mensaje); regreso; $ max_id = 0; Yii :: trace ('Count Statuses:' .count ($ tweets-> statuses)); Yii :: trace ('Max Tweet Id:'. $ Max_id); foreach ($ tweets-> estados como $ t) // verifica si el tweet está en un rango de tiempo válido $ unix_created_at = strtotime ($ t-> created_at); Yii :: trace ('Tweet @'. $ T-> created_at. ". $ Unix_created_at. ':'. $ T-> user-> screen_name.". (Isset ($ t-> text)? $ T-> texto: ")); if ($ unix_created_at> = $ valid_start && $ unix_created_at <= $valid_end) // print_r($t); $i = new Twitter(); $i->agregar ($ this-> id, $ t-> id_str, $ t-> usuario-> id_str, $ t-> usuario-> screen_name, $ unix_created_at, (isset ($ t-> texto)? $ t-> texto : ")); if ($ max_id == 0) $ max_id = intval ($ t-> id_str); else $ max_id = min ($ max_id, intval ($ t-> id_str));
Luego hacemos un bucle, realizando solicitudes repetidas a Twitter (hasta 179 veces más), solicitando registros adicionales que sean anteriores a la ID de tweet más baja del lote anterior. En otras palabras, en solicitudes posteriores, en lugar de consultar hasta una fecha específica, consultamos el ID máximo de la ID de tweet más baja que hemos recibido..
Nos detenemos cuando se devuelven menos de 100 registros o cuando los tweets devueltos son anteriores a nuestro rango real.
Si necesita acceder a más de 18,000 tweets, deberá implementar una tarea en segundo plano para llamar a la API de Twitter, como hemos hecho en nuestra otra serie de API de Twitter..
A medida que procesamos los resultados de la API, necesitamos filtrar los tweets, solo registrar aquellos que caen dentro de nuestra hora de inicio y finalización reales.
Nota: la API de Twitter tiene muchas peculiaridades frustrantes que hacen que la paginación sea más difícil de lo que debería ser. Con bastante frecuencia, Twitter no devuelve resultados sin un código de error. Otras veces, encontré que arrojaba una pequeña cantidad de resultados, pero eso no significaba que otra solicitud no devolviera más. No hay maneras muy claras de saber cuándo se termina la devolución de los resultados de Twitter. Es inconsistente Por lo tanto, puedes notar que mi código tiene algunas soluciones interesantes, por ejemplo. examinar $ count_max_repeats.
$ count_repeat_max = 0; // Realizar todas las consultas subsiguientes con la adición de maximum_tweet_id actualizado mientras ($ query_count<=$limit) $prior_max_id = $max_id; $query_count+=1; Yii::trace( 'Request #: '.$query_count); // Perform subsequent query with max_id $getfield ="?result_type=$result_type&geocode=".$this->latitude. ",". $ this-> longitude. ",". $ distance_km. "mi & include_entities = false & max_id = $ max_id & count = $ count"; $ tweets = json_decode ($ twitter-> setGetfield ($ getfield) -> buildOauth ($ url, $ requestMethod) -> performRequest ()); if (isset ($ tweets-> errores)) Yii :: $ app-> session-> setFlash ('error', 'Twitter Rate Limit Reached.'); Yii :: error ($ tweets-> errores [0] -> mensaje); regreso; // a veces la api de twitter falla si (! isset ($ tweets-> statuses)) continúa; Yii :: trace ('Count Statuses:' .count ($ tweets-> statuses)); Yii :: trace ('Max Tweet Id:'. $ Max_id); foreach ($ tweets-> estados como $ t) // verifica si el tweet está en un rango de tiempo válido $ unix_created_at = strtotime ($ t-> created_at); if ($ unix_created_at> = $ valid_start && $ unix_created_at <= $valid_end) $i = new Twitter(); $i->agregar ($ this-> id, $ t-> id_str, $ t-> usuario-> id_str, $ t-> usuario-> screen_name, $ unix_created_at, (isset ($ t-> texto)? $ t-> texto : ")); else if ($ unix_created_at < $valid_start) // stop querying when earlier than valid_start return; $max_id = min($max_id,intval($t->id_str)) - 1; if ($ prior_max_id - $ max_id <=1 OR count($tweets->estados)<1) $count_repeat_max+=1; if ($count_repeat_max>5) // cuando la API no está devolviendo más resultados; // termina mientras
Uno de los primeros resultados devueltos incluye el tweet a continuación de Fred Davenport que muestra al presidente Obama en el escenario:
Aquí está en Twitter:
Luego, a medida que navega por los resultados, puede encontrar muchas más personas presentes en Twitter sobre Obama, incluidos los medios de comunicación:
Ahora, hagamos una búsqueda más local..
Key Arena es el gran escenario deportivo y de conciertos de Seattle. El pasado fin de semana celebraron el Torneo de Baloncesto Femenino Pac-12:
Obtengamos nuestras coordenadas GPS para Key Arena de Google Maps:
Luego, creé y modifiqué un momento para encontrar un rango de tiempo más largo para el fin de semana de tweets:
Y, aquí están algunos de los resultados. Mi favorito es:
"Quiero dejar este juego de baloncesto. Odio el baloncesto".
En su mayor parte, me parece que la API de Instagram es mucho más poderosa que la de Twitter y produce resultados generalmente más interesantes. Sin embargo, depende del tipo de persona que estés buscando. Si solo quieres identificar a las personas que estaban allí, cualquiera de las dos API funciona bien.
Espero que hayas disfrutado esta serie. Me pareció fascinante y me impresionaron los resultados. Y destaca las preocupaciones que todos debemos tener sobre nuestro nivel de privacidad en esta era digital interconectada.
Las API para Instagram y Twitter son servicios increíblemente poderosos para encontrar usuarios de redes sociales que estuvieron cerca de ciertos lugares en ciertos momentos. Esta información puede ser usada para bien y puede ser abusada. Probablemente debería considerar desactivar su publicación de geolocalización: siga los enlaces en ¿Listo o No? aplicación.
También puede consultar mi serie Building with the Twitter API, también en Tuts+.
Por favor, siéntase libre de publicar sus preguntas y comentarios a continuación. También puedes contactarme en Twitter @reifman o enviarme un correo electrónico directamente. Apreciaría especialmente escuchar de periodistas y agentes de la ley que hacen uso de estos ejemplos..
También puede navegar por la página de mi instructor Tuts + para ver otros tutoriales que he escrito.