Это вторая из двух частей серии об использовании социальных сетей для поиска свидетелей важных событий. В первой части я показал вам, как использовать API Instagram, чтобы найти очевидцев для прямой видеосъемки «Макклемора» в Сиэтле. В этой части мы будем использовать API Twitter, чтобы найти участников выступления президента Обамы в Сельме на мосту Эдмунда Петтуса.
Вы можете скачать код для обоих эпизодов, используя ссылку на репозиторий GitHub на боковой панели. Вы также можете быть заинтересованы в моей серии Tuts +, Создание с помощью API Twitter .
Возможности Twitter для геоисследований более ограничены, и поэтому для их использования требуется более подробный код. Сообщения с геотегами в Twitter можно найти только за последние семь дней. И они доступны только для поиска по дате (а не по времени), поэтому вам нужно отфильтровать результаты API для точности.
Я участвую в обсуждениях ниже. Если у вас есть вопрос или предложение по теме, пожалуйста, оставьте комментарий ниже. Вы также можете связаться со мной в Twitter @reifman или написать мне напрямую.
Что мы рассмотрели в первой части
Телефоны, которые мы носим в наших карманах, записывают каждый наш шаг, делясь им с сотовыми провайдерами и часто сторонними компаниями-разработчиками программного обеспечения, мотивация которых, как правило, фокусируется на прибыли.
Многие люди не понимают, что они оставили геотеги в своих приложениях для социальных сетей, полностью публикуя информацию о своем местоположении в каждой публикации в социальных сетях. Это включало конгрессмена Республиканской партии Аарона Шока. AP использовал геотеги своего аккаунта в Instagram, чтобы разоблачить использование средств налогоплательщиков для экстравагантных частных перелетов и других роскошных мероприятий.
Таким образом, геотеггинг может быть использован навсегда. В этой серии мы исследуем, как журналисты или правоохранительные органы могут найти потенциальных свидетелей важных событий, таких как место преступления или происшествия, с помощью социальных сетей.
Тем не менее, геотеггинг также может быть использован неправомерно. Компьютерные ученые и преподаватели из Беркли построили Готово или Нет? приложение, чтобы продемонстрировать, как геотеггинг в 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/secure/eyew.ini
:
01
02
03
04
05
06
07
08
09
10
|
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.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<?php
use yii\db\Schema;
use yii\db\Migration;
class m150309_174014_create_twitter_table extends Migration
{
public function up()
{
$tableOptions = null;
if ($this->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 .
‘tweet_id’ => Schema::TYPE_BIGINT .
‘twitter_id’ => Schema::TYPE_BIGINT .
‘screen_name’ => Schema::TYPE_STRING .
‘text’ => Schema::TYPE_TEXT .
‘tweeted_at’ => Schema::TYPE_INTEGER .
‘created_at’ => Schema::TYPE_INTEGER .
‘updated_at’ => Schema::TYPE_INTEGER .
], $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}}’);
}
}
|
Как и в первой части , вам нужно запустить миграцию:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
./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?
*** 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, используя ссылку на боковую панель в этом руководстве, у вас также будет этот код.
Создать новый момент
Поскольку Твиттер ограничивает поиск геолокации на прошлой неделе, я в конечном итоге выбрал речь президента Обамы, посвященную 50-летию Сельмы, у моста Эдмунда Петтуса .
Я снова использовал Google Maps, чтобы получить координаты GPS для моста:
Затем я создал момент для речи для поиска. Я обновил его несколько раз, чтобы настроить географический радиус поиска (это мост) и временной диапазон:
Поиск с использованием Twitter API
Ограничения API Twitter состоят в том, что он позволяет выполнять поиск только по дате, например, 2015-03-07, тогда как Instagram индексируется по точным временным меткам Unix. Поэтому мы должны начать наш поиск в Твиттере на целый день вперед и искать в обратном направлении.
Поскольку мы, вероятно, получим много твитов за пределами желаемого диапазона времени, нам придется совершать повторные звонки в Twitter API. Twitter возвращает до 100 твитов на запрос API и разрешает 180 запросов за 15-минутное окно.
Я использую библиотеку Twitter API Джеймса Маллисона для PHP . Вот как мы настроили библиотеку для звонков:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
use app\models\Gram;
use Instagram;
use TwitterAPIExchange;
…
public function searchTwitter() {
date_default_timezone_set(‘America/Los_Angeles’);
Yii::trace(‘start searchTwitter ‘.date(‘ymd 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’],
);
// Connect to Twitter
$twitter = new TwitterAPIExchange($settings);
|
Первоначально мы запрашиваем 100 результатов из Twitter по нашим GPS-координатам до определенной даты.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public function searchTwitter() {
date_default_timezone_set(‘America/Los_Angeles’);
Yii::trace(‘start searchTwitter ‘.date(‘ymd 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’],
);
// Connect to Twitter
$twitter = new TwitterAPIExchange($settings);
// Query settings for search
$url = ‘https://api.twitter.com/1.1/search/tweets.json’;
$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 + duration
$valid_end = $this->start_at + ($this->duration*60);
Yii::trace( ‘Valid Range: ‘.$valid_start.’ -> ‘.$valid_end);
$until_date = date(‘Ym-d’,$valid_end+(24*3600));
$distance_km = $this->distance/1000;
// 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»;
|
Мы записываем твиты только в пределах нашего точного временного диапазона, игнорируя другие результаты. Обрабатывая их, мы отмечаем самый низкий полученный твит ID.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
$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();
}
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, как мы делали в нашей другой серии Twitter API .
Когда мы обрабатываем результаты API, нам нужно фильтровать твиты, записывая только те из них, которые соответствуют нашему фактическому времени начала и окончания.
Примечание. В API Twitter есть много неприятных особенностей, которые делают подкачку более сложной, чем она должна быть. Довольно часто Твиттер не возвращает результатов без кода ошибки. В других случаях я обнаружил, что он возвращает небольшое количество результатов, но это не значит, что другой запрос не вернет больше. Не существует очень четких способов узнать, когда Твиттер закончил, возвращая вам результаты. Это противоречиво. Таким образом, вы можете заметить, что в моем коде есть несколько интересных решений, например, изучить $ count_max_repeats.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
$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();
} 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
|
Один из первых возвращенных результатов включал в себя твит Фреда Дэвенпорта, показанный ниже, показывающий президента Обаму на сцене:
Вот это в Твиттере:
Затем, по мере того, как вы просматриваете результаты, вы можете найти гораздо больше людей, которые пишут в Твиттере об Обаме, включая СМИ:
Теперь давайте сделаем более локальный поиск.
Второй, более локальный поиск
Key Arena — большая концертная и спортивная арена Сиэтла. В прошедшие выходные они провели турнир по баскетболу среди женщин Pac-12:
Давайте получим наши GPS-координаты для Key Arena из Google Maps:
Затем я создал и настроил момент, чтобы найти больший диапазон времени для выходных твитов:
И вот некоторые из результатов. Мой любимый:
«Я хочу покинуть эту баскетбольную игру. Я ненавижу баскетбол».
По большей части мне кажется, что API Instagram гораздо более мощный, чем Twitter, и дает в целом более интригующие результаты. Однако это зависит от того, какого человека вы ищете. Если вы просто хотите идентифицировать людей, которые были там, любой API работает хорошо.
Что мы узнали
Надеюсь, вам понравился этот сериал. Я нашел это захватывающим и был впечатлен результатами. И это подчеркивает озабоченность, которую мы все должны проявлять в отношении уровня конфиденциальности в эту взаимосвязанную цифровую эпоху.
API для Instagram и Twitter — невероятно мощные сервисы для поиска пользователей социальных сетей, которые были в определенных местах в определенное время. Эта информация может быть использована для пользы и злоупотребления. Вам, вероятно, следует подумать об отключении публикации геолокации — перейдите по ссылкам Готов или Нет? приложение
Вы также можете ознакомиться с моей серией «Построение с помощью API Twitter» , также на Tuts +.
Пожалуйста, не стесняйтесь оставлять свои вопросы и комментарии ниже. Вы также можете связаться со мной в Twitter @reifman или написать мне напрямую. Я был бы особенно признателен журналистам и правоохранительным органам, которые используют эти примеры.
Вы также можете просмотреть мою страницу инструктора Tuts +, чтобы увидеть другие уроки, которые я написал.