Advertisement
  1. Code
  2. PHP

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

Scroll to top
Read Time: 11 min
This post is part of a series called Using Social Media to Locate Eyewitnesses.
Using Social Media to Locate Eyewitnesses to Important Events

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Tweet about President Obama taking the stage at SelmaTweet about President Obama taking the stage at SelmaTweet about President Obama taking the stage at Selma

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

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

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

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

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

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

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

Congressman Aaron Schock in South AmericaCongressman Aaron Schock in South AmericaCongressman Aaron Schock in South America

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

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

Вот Twitter-аккаунт соаснователя Apple Стив Возняка в этом приложении:

Ready or Not App Steve Wozniak Twitter Geolocation HistoryReady or Not App Steve Wozniak Twitter Geolocation HistoryReady or Not App Steve Wozniak Twitter Geolocation History

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

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

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

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

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

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

Macklemore Arrives Found with the Instagram APIMacklemore Arrives Found with the Instagram APIMacklemore Arrives Found with the Instagram API

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

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

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

Twitter App RegistrationTwitter App RegistrationTwitter App Registration

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

Twitter App Eyewitness DetailsTwitter App Eyewitness DetailsTwitter App Eyewitness Details

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

Twitter App DetailsTwitter App DetailsTwitter App Details

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

Twitter App Keys and Access TokensTwitter App Keys and Access TokensTwitter App Keys and Access Tokens

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

Twitter App Account Access TokensTwitter App Account Access TokensTwitter App Account Access Tokens

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

1
mysql_host="localhost"
2
mysql_db="eyew"
3
mysql_un="xxxxxxxxx"
4
mysql_pwd="xxxxxxxxxxxx"
5
instagram_client_id = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7"
6
instagram_client_secret = "1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4"
7
twitter_key = "zxxxxxxxxxxxxxxxxxxxx2"
8
twitter_secret ="4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxp"
9
twitter_oauth_token="1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxs"
10
twitter_oauth_secret="exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxV"

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

1
<?php
2
3
use yii\db\Schema;
4
use yii\db\Migration;
5
6
class m150309_174014_create_twitter_table extends Migration
7
{
8
    public function up()
9
    {
10
          $tableOptions = null;
11
          if ($this->db->driverName === 'mysql') {
12
              $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
13
          }
14
15
          $this->createTable('{{%twitter}}', [
16
              'id' => Schema::TYPE_PK,
17
              'moment_id' => Schema::TYPE_INTEGER . ' NOT NULL',
18
              'tweet_id' => Schema::TYPE_BIGINT . ' NOT NULL',
19
              'twitter_id' => Schema::TYPE_BIGINT . ' NOT NULL',
20
              'screen_name' => Schema::TYPE_STRING . ' NOT NULL DEFAULT 0',
21
              'text' => Schema::TYPE_TEXT . ' NOT NULL ',
22
              'tweeted_at' => Schema::TYPE_INTEGER . ' NOT NULL',
23
              'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',
24
              'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',
25
          ], $tableOptions);          
26
      $this->addForeignKey('fk_twitter_moment', '{{%twitter}}', 'moment_id', '{{%moment}}', 'id', 'CASCADE', 'CASCADE');     
27
    }
28
    
29
    
30
    public function down()
31
    {
32
      $this->dropForeignKey('fk_twitter_moment','{{%twitter}}');
33
      $this->dropTable('{{%twitter}}');
34
    }
35
}

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

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

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

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

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

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

Edmund Pettus Bridge Selma Alabama GeolocationEdmund Pettus Bridge Selma Alabama GeolocationEdmund Pettus Bridge Selma Alabama Geolocation

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

Edmund Pettus Bridge Selma Alabama Geolocation MomentEdmund Pettus Bridge Selma Alabama Geolocation MomentEdmund Pettus Bridge Selma Alabama Geolocation Moment

Поиск с помощью API Twitter

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

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

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

1
<?php
2
3
namespace app\models;
4
5
use Yii;
6
use yii\db\ActiveRecord;
7
use app\models\Gram;
8
use Instagram;
9
use TwitterAPIExchange;
10
11
...
12
13
public function searchTwitter() {
14
   date_default_timezone_set('America/Los_Angeles');       
15
   Yii::trace('start searchTwitter '.date('y-m-d h:m '));
16
   // Load your Twitter application keys

17
   $settings = array(
18
       'oauth_access_token' => \Yii::$app->params['twitter']['oauth_token'],
19
       'oauth_access_token_secret' => \Yii::$app->params['twitter']['oauth_secret'],
20
       'consumer_key' => \Yii::$app->params['twitter']['key'],
21
       'consumer_secret' => \Yii::$app->params['twitter']['secret'],
22
   );
23
   // Connect to Twitter 

24
   $twitter = new TwitterAPIExchange($settings);

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

1
public function searchTwitter() {
2
   date_default_timezone_set('America/Los_Angeles');       
3
   Yii::trace('start searchTwitter '.date('y-m-d h:m '));
4
   // Load your Twitter application keys

5
   $settings = array(
6
       'oauth_access_token' => \Yii::$app->params['twitter']['oauth_token'],
7
       'oauth_access_token_secret' => \Yii::$app->params['twitter']['oauth_secret'],
8
       'consumer_key' => \Yii::$app->params['twitter']['key'],
9
       'consumer_secret' => \Yii::$app->params['twitter']['secret'],
10
   );
11
   // Connect to Twitter 

12
   $twitter = new TwitterAPIExchange($settings);
13
   // Query settings for search

14
   $url = 'https://api.twitter.com/1.1/search/tweets.json';
15
   $requestMethod = 'GET';
16
   // rate limit of 180 queries

17
   $limit = 180;
18
   $query_count=1;
19
   $count = 100;
20
   $result_type = 'recent';
21
   // calculate valid timestamp range

22
   $valid_start = $this->start_at;
23
   // $until_date and $valid_end = // start time + duration

24
   $valid_end = $this->start_at + ($this->duration*60);
25
   Yii::trace( 'Valid Range: '.$valid_start.' -> '.$valid_end);
26
   $until_date = date('Y-m-d',$valid_end+(24*3600)); // add one day 

27
   $distance_km = $this->distance/1000; // distance in km

28
   // Unused: &since=$since_date

29
   // $since_date = '2015-03-05'; 

30
   // Perform first query with until_date

31
   $getfield ="?result_type=$result_type&geocode=".$this->latitude.",".$this->longitude.",".$distance_km."mi&include_entities=false&until=$until_date&count=$count";

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

1
       $tweets = json_decode($twitter->setGetfield($getfield)
2
                    ->buildOauth($url, $requestMethod)
3
                    ->performRequest());
4
        if (isset($tweets->errors)) {
5
          Yii::$app->session->setFlash('error', 'Twitter Rate Limit Reached.');
6
          Yii::error($tweets->errors[0]->message);
7
          return;
8
        }
9
       $max_id = 0;
10
       Yii::trace( 'Count Statuses: '.count($tweets->statuses));
11
       Yii::trace( 'Max Tweet Id: '.$max_id);
12
       foreach ($tweets->statuses as $t) {
13
         // check if tweet in valid time range

14
         $unix_created_at = strtotime($t->created_at);         
15
         Yii::trace('Tweet @ '.$t->created_at.' '.$unix_created_at.':'.$t->user->screen_name.' '.(isset($t->text)?$t->text:''));
16
         if ($unix_created_at >= $valid_start && $unix_created_at <= $valid_end)
17
         {
18
           // print_r($t);

19
            $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:''));
20
         }        
21
         if ($max_id ==0) {
22
           $max_id = intval($t->id_str);
23
         } else {
24
           $max_id = min($max_id, intval($t->id_str));
25
         }
26
       }

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

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

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

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

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

1
       $count_repeat_max =0;
2
       // Perform all subsequent queries with addition of updated maximum_tweet_id

3
       while ($query_count<=$limit) {
4
         $prior_max_id = $max_id;
5
         $query_count+=1;
6
         Yii::trace( 'Request #: '.$query_count);
7
         
8
         // Perform subsequent query with max_id

9
         $getfield ="?result_type=$result_type&geocode=".$this->latitude.",".$this->longitude.",".$distance_km."mi&include_entities=false&max_id=$max_id&count=$count";
10
         
11
         $tweets = json_decode($twitter->setGetfield($getfield)
12
                      ->buildOauth($url, $requestMethod)
13
                      ->performRequest());
14
15
          if (isset($tweets->errors)) {
16
            Yii::$app->session->setFlash('error', 'Twitter Rate Limit Reached.');
17
            Yii::error($tweets->errors[0]->message);
18
            return;
19
          }
20
          // sometimes twitter api fails

21
          if (!isset($tweets->statuses)) continue;
22
          
23
          Yii::trace( 'Count Statuses: '.count($tweets->statuses));
24
          Yii::trace( 'Max Tweet Id: '.$max_id);
25
         foreach ($tweets->statuses as $t) {           
26
           // check if tweet in valid time range

27
           $unix_created_at = strtotime($t->created_at);
28
           if ($unix_created_at >= $valid_start && $unix_created_at <= $valid_end)
29
           {
30
              $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:''));
31
           } else if ($unix_created_at < $valid_start) {
32
             // stop querying when earlier than valid_start

33
             return;
34
           }
35
           $max_id = min($max_id,intval($t->id_str))-1;
36
         }       
37
         if ($prior_max_id - $max_id <=1 OR count($tweets->statuses)<1) {
38
           $count_repeat_max+=1;
39
         }           
40
         if ($count_repeat_max>5) {           
41
           // when the api isn't returning more results

42
           break;
43
         }
44
       } // end while 

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

The First Results for Selma 50th via the Twitter Search APIThe First Results for Selma 50th via the Twitter Search APIThe First Results for Selma 50th via the Twitter Search API

Вот это на Twitter:

President Obama in Selma via the Twitter API President Obama in Selma via the Twitter API President Obama in Selma via the Twitter API

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

More Selma Twitter API ResultsMore Selma Twitter API ResultsMore Selma Twitter API Results

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

Второй, более локальный поиск

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

Key Arena Calendar of EventsKey Arena Calendar of EventsKey Arena Calendar of Events

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

Key Arena Geolocation on Google MapsKey Arena Geolocation on Google MapsKey Arena Geolocation on Google Maps

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

Create a moment to search Key Arena Basketball TournamentCreate a moment to search Key Arena Basketball TournamentCreate a moment to search Key Arena Basketball Tournament

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

«Я хочу оставить эту игру в баскетбол. Я ненавижу баскетбол."
Twitter Search Results for Key Arena TournamentTwitter Search Results for Key Arena TournamentTwitter Search Results for Key Arena Tournament

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

Что мы узнали

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

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

Вы также можете ознакомиться с моей серией статей Работаем с API Twitter на Tuts +.

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

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

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

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.