() translation by (you can also view the original English article)



Ini adalah bagian kedua dari serial dua bagian tentang menggunakan media sosial untuk menemukan lokasi para saksi mata kejadian-kejadian penting. Di bagian pertama, saya menunjukkan pada Anda cara menggunakan API Instagram untuk menemukan saksi mata tayangan langsung syuting video Macklemore di Seattle. Di bagian ini, kami akan menggunakan Twitter API untuk menemukan orang yang menghadiri pidato Presiden Obama di Selma, Jembatan Edmund Pettu.
Anda bisa mengunduh kode bagi dua episode tersebut dengan menggunakan tautan yang disimpan di Github, di sidebar. Anda mungkin tertarik dengan seria Tuts+ saya, Membangun dengan API Twitter.
Kapabilitas pencarian geo Twitter lebih terbatas dan oleh karenanya membutuhkan kode yang sedikit lebih detail. Kiriman dengan geotag di Twitter hanya bisa ditemukan dalam tujuh hari terakhir. Dan hanya bisa dicari berdasarkan tanggal (bukan waktu), jadi Anda harus memfilter hasil pencarian API agar presisi.
Saya sungguh akan berpartisipasi dalam diskusi di bawah artikel ini. Jika Anda ada pertanyaan atau usulan topik, silakan kirimkan komentar di bawah ini. Anda juga bisa menghubungi saya di Twitter @reifman atau email saya secara langsung.
Apa yang Kami Bahas di Bagian Pertama
Telepon yang kita bawa di saku merekam setiap pergerakan kita, membagikannya dengan penyedia layanan seluler dan seringkali juga dengan perusaaan perangkat lunak pihak ketiga yang motivasinya berfokus pada keuntungan.
Banyak orang yang tidak menyadari bahwa mereka meninggalkan geotag di aplikasi media sosial mereka, sepenuhnya mempublikasikan lokasinya di tiap kiriman media sosial. Termasuk juga anggota Kongres AS dari Partai Republik Aaron Schock. Dia menggunakan geotag akun instagramnya untuk mengekspos penggunaan dana pembayar pajak untuk penerbangan pribadi yang mewah dan berbagai aktivitas glamor lainnya.
Jadi geotagging bisa digunakan dengan baik. Di serial ini, kami mengeksplorasi cara yang mungkin dilakukan para wartawan dan penegak hukum untuk menemukan lokasi saksi mata potensial terhadap even-even penting seperti kejadian kejahatan atau kecelakaan dengan menggunakan media sosial.
Meskipun demikian, geotangging juga bisa disalahgunakan. Beberapa ilmuwan dan pengajar komputer Berkeley membuat aplikasi Ready or Not? untuk mendemonstrasikan bagaimana geotagging Twitter dan Instagram merekam semua pergerakan kita.
Berikut akun Twitter pendiri Apple Steve Wozniak di aplikasi tersebut:



Geotagging di Instagram dan Twitter cukup akurat untuk memungkinkan seseorang dengan mudah menentukan tempat tinggal, tempat kerja, dan rute perjalanan rutin Anda.
Di episode ini, akan saya pandu Anda menggunakan Twitter API. Saya menyediakan suatu tempat di Github (tautannya ada di sidebar) untuk Anda unduh dan coba kodenya. Aplikasi "Eyewitness" saya ditulis dalam Framework Yii untuk PHP, yang bisa Anda pelajari lebih lanjut di seri Pemrograman dengan Yii2 untuk Tuts+ saya.
Jika Anda tidak ingin membagikan lokasi Anda ke publik—atau meninggalkan jejak sejarah dalam perjalanan Anda—aplikasi Ready or Not? menawarkan tautan dan panduan untuk mematikan fitur ini (lihat tautannya di home pagenya). Sejujurnya, saya mematikan punya saya dan saya mendorong Anda untuk melakukannya juga.
Jika Anda adalah agen penegakan hukum atau entitas media yang ingin tahu lebih banyak tentang informasi ini, jangan ragu menghubungi saya secara langsung. Saya juga akan tertarik dengan penggunaan kode ini yang berhasil (untuk kebaikan)—tentu akan membuat cerita tindak lanjut yang menarik.
Apa yang Kami Lakukan dengan Instagram
Di episode terakhir, kami menggunakan Instagram API untuk menemukan saksi mata syuting video langsung Mackelmore 2013 untuk White Cadillac. Dengan cukup mudah, kami berhasil menemukan foto Macklemore keluar dari kendaraannya oleh pengguna Instagram Joshua Lewis (keren, kan?):



Sekarang mari mulai menggunakan Twitter API.
menggunakan Twitter API
Sama dengan Instagram, Anda harus masuk ke akun Twitter Anda dan mendaftar aplikasi developer. Anda harus mendaftarkan aplikasi seperti ini:



Twitter akan menunjukkan Anda detail aplikasinya:



Berikut halaman pengaturannya:



Berikut adalah kunci dan token akses aplikasinya. Catat dengan baik.



Lalu, tarik ke bawah dan buat token akses untuk akun Anda. Catat juga yang itu.
Masukkan keempat kunci konfigurasi dan rahasianya ke file /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" |
Lalu, kita akan membuat migrasi Active Record untuk membuat model Twitter kita. Ini akan menyimpan cuitan-cuitan yang kita terima dari panggilan-panggilan 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 |
}
|
Seperti yang kita lakukan di bagian pertama, Anda harus menjalankan migrasinya:
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. |
Lalu saya menggunakan generator kode Yii2, Gii, untuk membuat model dan kontroler CRUD bagi model Twitter. Jika Anda memiliki kode repository GitHub yang terbaru dari tautan di sidebar tutorial ini, Anda juga akan memiliki kodenya.
Buat Momen Baru
Karena Twitter membatasi pencarian geolokasi hanya ke pekan terakhir, akhirnya saya memilih pidato Presiden Obama pada Hari Jadi ke-50 Selma di Jembatan Edmunnd Pettus.
Sekali lagi saya menggunakan Google Maps untuk mendapatkan koordinat GPS jembatannya:



Lalu saya membuat Moment untuk mencari pidatonya. Saya memperbaruinya beberapa kali untuk memperbaiki radius geografis pencariannya (ini sebuah jembatan) dan kisaran waktunya:



Pencarian Menggunakan Twitter API
Pembatasan pada Twitter API adalah Anda hanya dimungkinkan mencari berdasarkan tanggal, misalnya 2015-03007, sedangkan Instagram diindeks berdasarkan waktu Unix yang tepat. Oleh karena itu, kami mulai pencarian Twitter kami sehari penuh setelahnya dan pencarian sebelumnya.
Karena kita sepertinya akan mendapatkan banyak cuitan di luar kisaran waktu yang diharapkan, kita harus melakukan pemanggilan berulang-ulang ke Twitter API. Twitter mengembalikan 100 cuitan per permintaan API, dan memperbolehkan 180 permintaan per jendela 15 menit.
Saya menggunakan James Mallison's Twitter API Library for PHP. Berikut cara kami mengatur library untuk membuat panggilan:
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); |
Pada awalnya, kami meminta 100 hasil dari Twitter dengan koordinat GPS kami hingga tanggal tertentu.
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"; |
Kami hanya merekam cuitan dalam kisaran waktu yang tepat serta mengabaikan hasil-hasil lainnya. Seiring kami memroses ini, kami membuat catatan tentang ID cuitan terendah yang diterima.
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 |
}
|
Lalu kami loop, melakukan permintaan berulang ke Twitter (sampai 179 kali lagi), meminta rekaman-rekaman tambahan yang lebih awal daripada ID cuitan gelombang sebelumnya. Dengan kata lain, di permintaan berikutnya, alih-alih mencari ke tanggal tertentu, kami membuat kueri ke max_id dari ID cuitan terendah yang kami terima:
Kami berhenti ketika yang dikembalikan kurang dari 100 rekaan atau ketika cuitan yang dikembalikan lebih awal daripada kisaran waktu aktualnya.
Jika Anda butuh mengakses lebih dari 18.000 cuitan, Anda harus mengimplementasikan tugas latar belakang (background task) untuk memanggil Twitter API, sebagaimana yang kami lakukan di seri Twitter API yang lainnya.
Sebagaimana kami memroses hasil-hasil API, kami harus memfilter cuitan-cuitan, hanya merekam yang ada dalam kisaran antara waktu aktual dimulai dan diakhirinya even tersebut.
Catatan: Twitter API punya banyak kekhasan yang membuat frustrasi, yang menjadikan paging lebih sulit daripada seharusnya. Seringkali Twitter tidak mengembalikan hasil apapun tanpa kode kesalahan. Di waktu lainnya, saya mendapati Twitter mengembalikan sejumlah kecil hasil, tetapi tidak berarti permintaan lainnya tidak akan mengembalikan yang lebih banyak. Tidak ada cara yang jelas untuk memhahami kapan Twitter selesai mengembalikan hasilnya untuk Anda. Sifatnya tidak konsisten. Jadi, Anda mungkin mendapati beberapa pemecahan masalah menarik di kode saya, misalnya perhatikan $sount_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 |
Salah satu hasil pertama yang dikembalikan termasuk cuitan di bawah ini oleh Fred Davenport yang menunjukkan Presiden Obama di panggung:



Berikut di Twitter:



Lalu, seiring Anda mencari hasil lebih jauh, Anda bisa menemukan lebih banyak orang membuat cuitan tentang Obama—termasuk media:



Sekarang, mari melakukan pencarian yang lebih lokal.
Sedetik, Pencarian yang Lebih Lokal
Key Arena adalah arena olahraga dan konser besar di Seattle. Pekan terakhir ini ada Turnamen Basket Wanita Pac-12:



mari dapatkan koordinat GPS untuk Key Arena dari Google Maps:



Lalu, saya membuat dan menyesuaikan suatu momen untuk menemukan kisaran waktu yang lebih panjang di akhir pekan untuk cuitan-cuitannya:



Dan, berikut beberapa hasilnya. Favorit saya adalah:
"Saya ingin meninggalkan pertandingan basket ini. Saya benci bola basket."



Untuk sebagian besarnya, sepertinya Instagram API jauh lebih hebat daripada Twitter dan secara umum hasilnya lebih menarik. Meskipun demikian, itu tergantung pada jenis orang yang Anda cari. Jika Anda hanya ingin mengidentifikasi siapa saja yang ada di sana, API manapun tidak akan bekerja dengan baik.
Apa yang Kami Pelajari
Saya harap Anda menikmati seri ini. Saya mendapati ini sebagai sesuatu yang menyenangkan dan terkesan dengan hasilnya. Tutorial ini sekaligus menyoroti kekhawatiran yang seharusnya kita miliki tentang tingkat privasi kita di zaman digital yang saling terhubung ini.
API untuk Instagram dan Twitter sama-sama bagus dalam menemukan pengguna-pengguna media sosial yang berada di dekat tempat-tempat tertentu pada waktu-waktu tertentu. Informasi ini bisa digunakan untuk tujuan yang baik dan bisa juga disalahgunakan. Seharusnya Anda mempertimbangkan untuk mematikan kiriman geolokasi Anda—ikuti tautan-tautan di aplikasi Ready or Not?.
Anda mungkin juga berkenan mempelajari seri saya di Tuts+ Membangun dengan Twitter API.
Jangan ragu mengirimkan pertanyaan-pertanyaan dan komentar Anda di bawah ini. Anda juga bisa menghubungi saya di Twitter @reifman atau kirimkan email langsung ke saya. Saya pada khususnya mengapresiasi untuk mendengar dari para wartawan dan penegak hukum yang memanfaatkan contoh-contoh ini.
Anda juga bisa menjelajahi halaman instruktur Tuts+ saya untuk melihat tutorial-tutorial lainnya yang telah saya tulis.
Tautan-Tautan Terkait
- Twitter API
- Instagram API
- Ready or Not? (Pembelajaran Privasi)
- Bagaimana Kita Menangkap Penulis Majalah Wired yang Hilang Evan Ratliff
- Yii2 Developer Exchange