Использование социальных сетей для поиска очевидцев: API Twitter

21 января 2018

Это вторая серия из двух частей, посвященная использованию социальных сетей для поиска очевидцев важных событий. В первой части я показал вам, как использовать Instagram API, чтобы найти свидетелей живой видеоролик Макклерора в Сиэтле. В этой части мы используем API Twitter для поиска участников речи президента Обамы в Сельме на мосту Эдмунда Петтуса.

Вы можете загрузить код для обоих эпизодов, используя ссылку репозитория GitHub на боковой панели. Вы также можете быть заинтересованы в моей серии Tuts +, созданной с помощью API Twitter.

Возможности геопоиск Twitter более ограничены и поэтому требуют более подробного кода для использования. Geotagged сообщений в Twitter можно найти только за последние семь дней. И они доступны только по дате (а не по времени), поэтому вам нужно фильтровать результаты API для точности.

Я участвую в обсуждениях ниже. Если у вас есть вопрос или предложение, пожалуйста, напишите комментарий ниже. Вы также можете связаться со мной в Twitter @reifman или отправить мне электронное письмо прямо.

То, что мы рассмотрели в первой части

Телефоны, которые мы носим в наших карманах, записывают каждое наше движение, делясь с поставщиками сотовых телефонов и часто сторонними компаниями-разработчиками программного обеспечения, чьи мотивации в основном фокусируются на прибыли.

Многие люди не понимают, что они оставили геотаггинг в своих приложениях в социальных сетях, полностью рекламируя свое местоположение с каждым сообщением в социальных сетях. Это включало конгрессмена Республиканской партии Аарона Шока. AP использовала свои учетные записи Instagram, чтобы разоблачить использование средств налогоплательщика для экстравагантных частных рейсов и других роскошных мероприятий.

Таким образом, геотегов можно использовать навсегда. В этой серии мы изучаем, как журналисты и правоохранительные органы могут найти потенциальных очевидцев для важных событий, таких как преступление или происшествие с использованием социальных сетей.

Однако геотаггинг также можно использовать оскорбительно. Беркли компьютерных ученых и педагогов построили Ready или нет? приложение, чтобы продемонстрировать, как геотаггинг в Twitter и Instagram записывают каждый наш ход.

Вот ваша учетная запись Apple в соавторстве Стив Узняк в приложении:

Геотегинг на Instagram и Twitter достаточно точен, чтобы кто-то мог легко определить ваше место жительства, место работы и обычную поездку.

В этом эпизоде ​​я проведу вас через API Twitter. Я предоставил репозиторий GitHub (ссылка находится на боковой панели), чтобы скачать его, чтобы попробовать код. «Приложение для свидетелей» написано в Yii Framework для PHP, о котором вы можете узнать больше в своем программировании с помощью серии Yii2 для Tuts +.

Если вы не хотите делиться своим местоположением с общественностью, чтобы увидеть - или оставить исторический след ваших путешествий - Готов или нет? приложение предлагает ссылки и руководства по отключению этих функций (найдите ссылку на своей домашней странице). Честно говоря, я отключил себя, и я призываю вас сделать это тоже.

Если вы являетесь правоохранительным органом или медиа-субъектом, который хотел бы получить дополнительную информацию, пожалуйста, свяжитесь со мной напрямую. Я также был бы заинтересован в любом успешном использовании этого кода (навсегда) - они сделают интересную последующую историю.

Что мы сделали с Instagram

Последний эпизод, мы использовали API Instagram, чтобы найти свидетелей для видеоролика Mackelmore в 2013 году для White Cadillac. Довольно легко нам удалось найти член Instagram Джошуа Льюис, фотография Маклемора, выходящего из его автомобиля (круто, да?):

Теперь давайте начнем использовать API Twitter.

Использование API Twitter

Как и в случае с Instagram, вам необходимо войти в свою учетную запись Twitter и зарегистрировать приложение разработчика. Вы должны зарегистрировать приложение, подобное этому:

Twitter покажет вам ваши данные о приложении:

Вот страница настроек:

Вот ключи и токены доступа для приложения. Обратите внимание на это.

Затем прокрутите вниз и создайте токены доступа для своей учетной записи. Имейте это в виду.

Добавьте все четыре из этих конфигураций ключей и секретов для файла var eyew.ini в файле:

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"

Затем мы создадим миграцию Active Record, чтобы создать нашу модель Twitter. Это сохранит твиты, которые мы получаем от вызовов API.

<?php
use yiidbSchema;
use yiidbMigration;
class m150309_174014_create_twitter_table extends Migratio
{
    public function up()
    {
          $tableOptions = null;
          if ($this->db->driverName === 'mysql') {
              $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=IoDB';
          }
          $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');    
    }
    public function down()
    {
      $this->dropForeignKey('fk_twitter_moment','{{%twitter}}');
      $this->dropTable('{{%twitter}}');
    }
}

Как и в первой части, вам нужно выполнить миграцию:

./yii migrate/up
Yii Migration Tool (based on Yii v2.0.3)
Total 1 new migration to be applied:
    m150309_174014_create_twitter_table
Apply the above migration? (yes|no) [no]:yes
*** applying m150309_174014_create_twitter_table
    > create table {{%twitter}} ... done (time: 0.008s)
    > add foreign key fk_twitter_moment: {{%twitter}} (moment_id) references {{%moment}} (id) ... done (time: 0.007s)
*** applied m150309_174014_create_twitter_table (time: 0.019s)
Migrated up successfully.

Затем я использовал генератор кода Yii2, Gii, чтобы создать модель и CRUD-контроллеры для модели Twitter. Если вы получите последний код репозитория GitHub, используя ссылку боковой панели в этом учебнике, у вас тоже будет код.

Создать новый момент

Поскольку Twitter ограничивает поиск геолокации на прошлой неделе, я в конечном итоге выбрал пятилетнюю годовщину президента Салмы на мосту Эдмунда Петтуса.

Я снова использовал Карты Google, чтобы получить координаты GPS для моста:

Затем я создал Момент для речи для поиска. Я несколько раз обновил его, чтобы настроить географический радиус поиска (его мост) и временной диапазон:

Поиск с использованием API Twitter

Ограничения API Twitter - это то, что он разрешает вы можете искать по дате, например 2015-03-07, тогда как Instagram индексируется точными отметками времени Unix. Поэтому мы должны начать наш поиск в Twitter на целый день вперед и искать назад.

Поскольку мы, скорее всего, получим много твитов за пределами желаемого диапазона времени, мы должны повторять вызовы API Twitter. Twitter возвращает до 100 твитов за запрос API и позволяет 180 запросов в 15-минутном окне.

Я использую библиотеку API Twitter Джеймса Мэллисона для PHP. Вот как мы настраиваем библиотеку для совершения вызовов:

<?php
amespace appmodels;
use Yii;
use yiidbActiveRecord;
use appmodelsGram;
use Instagram;
use TwitterAPIExchange;
...
public function searchTwitter() {
   date_default_timezone_set('America/Los_Angeles');      
   Yii::trace('start searchTwitter '.date('y-m-d h:m '));
   // Load your Twitter application keys
   $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'],
   );
   // Coect to Twitter
   $twitter = new TwitterAPIExchange($settings);

Первоначально мы запрашиваем 100 результатов от Twitter по нашим GPS-координатам до определенной даты.

public function searchTwitter() {
   date_default_timezone_set('America/Los_Angeles');      
   Yii::trace('start searchTwitter '.date('y-m-d h:m '));
   // Load your Twitter application keys
   $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'],
   );
   // Coect to Twitter
   $twitter = new TwitterAPIExchange($settings);
   // Query settings for search
   $url = 'https://api.twitter.com/1.1/search/tweets.jso';
   $requestMethod = 'GET';
   // rate limit of 180 queries
   $limit = 180;
   $query_count=1;
   $count = 100;
   $result_type = 'recent';
   // calculate valid timestamp range
   $valid_start = $this->start_at;
   // $until_date and $valid_end = // start time + duratio
   $valid_end = $this->start_at + ($this->duration*60);
   Yii::trace( 'Valid Range: '.$valid_start.' -> '.$valid_end);
   $until_date = date('Y-m-d',$valid_end+(24*3600)); // add one day
   $distance_km = $this->distance/1000; // distance in km
   // Unused: &since=$since_date
   // $since_date = '2015-03-05';
   // Perform first query with until_date
   $getfield ="?result_type=$result_type&geocode=".$this->latitude.",".$this->longitude.",".$distance_km."mi&include_entities=false&until=$until_date&count=$count";

Мы записываем только твиты в пределах нашего точного диапазона времени, игнорируя другие результаты. Когда мы обрабатываем их, мы учитываем самый низкий идентификатор твита.

$tweets = json_decode($twitter->setGetfield($getfield)
             ->buildOauth($url, $requestMethod)
             ->performRequest());
 if (isset($tweets->errors)) {
   Yii::$app->session->setFlash('error', 'Twitter Rate Limit Reached.');
   Yii::error($tweets->errors[0]->message);
   return;
 }
$max_id = 0;
Yii::trace( 'Count Statuses: '.count($tweets->statuses));
Yii::trace( 'Max Tweet Id: '.$max_id);
foreach ($tweets->statuses as $t) {
  // check if tweet in valid time range
  $unix_created_at = strtotime($t->created_at);        
  Yii::trace('Tweet @ '.$t->created_at.' '.$unix_created_at.':'.$t->user->screen_name.' '.(isset($t->text)?$t->text:''));
  if ($unix_created_at >= $valid_start && $unix_created_at <= $valid_end)
  {
    // print_r($t);
     $i = new Twitter();           $i->add($this->id,$t->id_str,$t->user->id_str,$t->user->screen_name,$unix_created_at,(isset($t->text)?$t->text:''));
  }       
  if ($max_id ==0) {
    $max_id = intval($t->id_str);
  } else {
    $max_id = min($max_id, intval($t->id_str));
  }
}

Затем мы зацикливаемся, повторяя запросы в Twitter (до 179 раз), запрашивая дополнительные записи, которые раньше, чем предыдущий самый младший идентификатор твита. Другими словами, при последующих запросах вместо запроса до определенной даты мы запрашиваем max_id самого низкого идентификатора чириканья, который мы получили.

Мы останавливаемся, когда возвращается менее 100 записей или когда возвращенные твиты ранее нашего реального диапазона.

Если вам нужен доступ к более чем 18 000 твитов, вам нужно будет выполнить фоновое задание, чтобы вызвать API Twitter, как мы это сделали в нашей другой серии API Twitter.

Когда мы обрабатываем результаты API, нам нужно фильтровать твиты, записывая только те, которые относятся к нашему фактическому времени начала и окончания.

Примечание: API Twitter имеет много разочаровывающих причуд, которые делают пейджинг сложнее, чем должно быть. Довольно часто Twitter не возвращает никаких результатов без кода ошибки. В других случаях я обнаружил, что он возвращает небольшое количество результатов, но это не означает, что другой запрос не вернет больше. Нет четких способов узнать, когда Twitter будет делать результаты для вас. Это непоследовательно. Таким образом, вы можете заметить, что мой код содержит несколько интересных обходных решений, например. изучите $ count_max_repeats.

$count_repeat_max =0;
// Perform all subsequent queries with addition of updated maximum_tweet_id
while ($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->errors)) {
     Yii::$app->session->setFlash('error', 'Twitter Rate Limit Reached.');
     Yii::error($tweets->errors[0]->message);
     return;
   }
   // sometimes twitter api fails
   if (!isset($tweets->statuses)) continue;
   Yii::trace( 'Count Statuses: '.count($tweets->statuses));
   Yii::trace( 'Max Tweet Id: '.$max_id);
  foreach ($tweets->statuses as $t) {          
    // check if tweet in valid time range
    $unix_created_at = strtotime($t->created_at);
    if ($unix_created_at >= $valid_start && $unix_created_at <= $valid_end)
    {
       $i = new Twitter();           $i->add($this->id,$t->id_str,$t->user->id_str,$t->user->screen_name,$unix_created_at,(isset($t->text)?$t->text:''));
    } 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->statuses)<1) {
    $count_repeat_max+=1;
  }          
  if ($count_repeat_max>5) {          
    // when the api isn't returning more results
    break;
  }
} // end while

Один из первых результатов, которые были возвращены, включал твит, показанный Фредом Давенпортом, показывающий президента Обаму на сцене:

. Вот он на Twitter:

Затем, когда вы просматриваете результаты дальше, вы можете найти еще много люди преподают об Обаме, в том числе в средствах массовой информации:

Теперь давайте сделаем более локальный поиск.

A Второй, более местный поиск

Key Arena - крупная концертная и спортивная арена в Сиэтле. В прошлый уик-энд они провели турнир по баскетболу среди женщин Pac-12:

Давайте получим наши GPS-координаты для Key Arena с Google Maps:

Затем я создал и изменил момент, чтобы найти более длинный диапазон времени для выходных твитов:

И вот некоторые из результатов. Мое любимое занятие:

«Я хочу оставить эту баскетбольную игру. Я ненавижу баскетбол.

По большей части мне кажется, что API Instagram намного мощнее, чем Twitter и дает, как правило, более интригующие результаты. Однако это зависит от того человека, которого вы ищете. Если вы просто хотите идентифицировать людей, которые там были, либо API работает хорошо.

Что мы узнали

Надеюсь, вам понравилась эта серия. Я нашел его увлекательным и был впечатлен результатами. И в нем подчеркивается, что мы все должны заботиться о нашем уровне конфиденциальности в этой взаимосвязанной цифровой эпохе.

API для Instagram и Twitter - невероятно мощные услуги для поиска пользователей социальных сетей, которые находились поблизости от определенных мест в определенное время. Эта информация может быть использована навсегда, и ее можно злоупотреблять. Вероятно, вам стоит подумать об отключении проводки геолокации - следуйте ссылкам на Ready или Not? приложение.

Вы также можете проверить мое здание с помощью API-интерфейса Twitter, также на Tuts +.

Пожалуйста, не стесняйтесь оставлять свои вопросы и комментарии ниже. Вы также можете связаться со мной в Twitter @reifman или отправить мне электронное письмо прямо. Я особенно ценю услышать от журналистов и правоохранительных органов, которые используют эти примеры.

Вы также можете просмотреть мою страницу инструкторов Tuts +, чтобы увидеть другие учебники, которые я написал.

Ссылки по теме

Интернет-интерфейс API Инструкция Instagram Значит или нет? (Преподавание конфиденциальности) Как мы поймали пропавших Wired Magazine Writer Эван Ratliff Yii2 Developer Exchange