PHPを使った位置情報収集(ラブライバーはどこから来るの?)

標準

開発に至った経緯

9月29日、30日に「Aqours 2nd ラブライブ! HAPPY PARTY TRAIN TOUR 埼玉公園」(公式サイト)が開催されまして、1日目に私はライブ・ビューイングに参戦しました。(2日目は残念ながらTwitterを眺めるだけでしたが😥)(感想は後述)
そこで、ライブのために埼玉まで来た方はどこから来ているのかと言うのを簡易的に調査するために、Twitterを使った位置情報収集アプリを作ることにしました。

調査方式

  1. ある任意の座標(今回は西武ドームの 35.768653,139.419132 / 国土地理院の地図)をプログラムに与えると、その地点の半径1km以内で投稿されたツイートを集めます。
  2. そのツイート主を全員それぞれ200ツイートずつ遡ってツイートを取得します。
  3. その中でジオタグ(位置情報)があれば集めます。
  4. Excelで収集したデータセットを整理します。
  5. 最後にそれを地図に出力します。

といった感じで、本当に簡易的です。

コード

<!DOCTYPE html>
<html lang="ja">
<head>
    <title>Twitter trace</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="index.css" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
    <?php
    ini_set('display_errors', 1);
    require_once(__DIR__ . "/twitteroauth/autoload.php");
    use Abraham\TwitterOAuth\TwitterOAuth;
    $consumer_key = "***************";
    $consumer_secret = "****************************************************";
    $access_token = "***************************************************";
    $access_token_secret = "*******************************************";

    $connection = new TwitterOAuth($consumer_key, $consumer_secret, $access_token, $access_token_secret);

    ////////////////////////////////////////
    $count_limit = (int)"100"; //0-100
    $get_users_status = (int)"200"; //0-200
    $default_lat = "35.768653";
    $default_long = "139.419132";
    ////////////////////////////////////////

    if(isset($_GET["lat"]) && isset($_GET["long"]) && $_GET["lat"] != "" && $_GET["long"] != "") {
        $set_lat = $_GET["lat"];
        $set_long = $_GET["long"];
    } else {
        $set_lat = $default_lat;
        $set_long = $default_long;
    }

    if(isset($_GET["max_id"]) && $_GET['max_id'] != "") {
        $max_id = $_GET["max_id"];
    } else {
        $max_id = "";
    }

    $geo_params = Array(
        "geocode" => "{$set_lat},{$set_long},1.0km",
        "count" => $count_limit,
        "result_type" => "mixed",
        "max_id" => $max_id,
        "include_entities" => false

    );

    $result_tweets = $connection->get("search/tweets", $geo_params);

    $result_tweets_array = json_decode(json_encode($result_tweets),true);

    $result_coordinate = Array();
    $oldest_id = "";
    $debug_info = "";

    $i = (int)"0";
    while (true) {
        $debug_info .= "{$i}\r\n";
        $status = $result_tweets_array["statuses"][$i];
        if($created_at = $status["created_at"] == "") {
            break;
        }
        $screen_name = $status["user"]["screen_name"];
        $lat = $status["geo"]["coordinates"][0];
        $long = $status["geo"]["coordinates"][1];

        if($screen_name != "mgn_tokorozawa") {
            if($lat != "" && $long != "") {
                array_push($result_coordinate,Array("lat" => $lat,"long" => $long));
            }
        }

        $users_info = Array(
            "screen_name" => $screen_name,
            "count" => $get_users_status,
            "exclude_replies" => true,
            "include_rts" => false,
            "trim_user" => true,
            "exclude_replies" => true
        );

        $users_data = $connection->get("statuses/user_timeline",$users_info);

        $users_data_array = json_decode(json_encode($users_data),true);

        $i2 = (int)"0";
        while(true) {
            $status_data = $users_data_array[$i2];
            if($status_data["geo"] != "" && $lat != $status_lat && $long != $status_long) {
                $status_lat = $status_data["geo"]["coordinates"][0];
                $status_long = $status_data["geo"]["coordinates"][1];
                $debug_info .= "status_lat:{$status_lat}\r\n";
                $debug_info .= "status_long:{$status_long}\r\n";
                $debug_info .= "http://maps.gsi.go.jp/#16/{$status_lat}/{$status_long}/&base=std\r\n";
                if ($screen_name != "mgn_tokorozawa") {
                    if($status_lat != "" && $status_long != "") {
                        array_push($result_coordinate,Array("lat" => $status_lat,"long" => $status_long));
                    }
                }
            }

            $i2++;
            if($i2 >= $get_users_status) {
                break;
            }
        }

        if ($status['id'] != "") {
            $oldest_id = $status['id'];
        }

        $debug_info .= "screen_name:{$screen_name}\r\n";
        $debug_info .= "id:{$status['id']}\r\n";
        $debug_info .= "text:{$status['text']}\r\n";
        $debug_info .= "lat:{$lat}\r\n";
        $debug_info .= "long:{$long}\r\n";
        $debug_info .= "http://maps.gsi.go.jp/#16/{$lat}/{$long}/&base=std\r\n";
        $debug_info .= "https://twitter.com/{$status['user']['screen_name']}/status/{$status['id']}\r\n=================\r\n";
        $i++;
        if($i >= $count_limit) {
            break;
        }
    }

    $api_limit_info = $connection->get("application/rate_limit_status");
    $api_limit_info_array = json_decode(json_encode($api_limit_info),true);
    ?>
    <div class="container" id="main">
        <?php
        echo "<h2>API LIMIT INFO</h2>";
        echo "<ul class='list-group'><li>/search/tweets:{$api_limit_info_array['resources']['search']['/search/tweets']['remaining']}/{$api_limit_info_array['resources']['search']['/search/tweets']['limit']}</li>";
        echo "<li>/statuses/user_timeline:{$api_limit_info_array['resources']['statuses']['/statuses/user_timeline']['remaining']}/{$api_limit_info_array['resources']['statuses']['/statuses/user_timeline']['limit']}</li></ul>";

        $result = (int)"0";
        $result_count = count($result_coordinate);
        $output = (string)"";
        while(true) {
            $output .= "{lat: {$result_coordinate[$result]['lat']},lng: {$result_coordinate[$result]['long']}},";
            $result++;
            if($result >= $result_count) {
                break;
            }
        }
        ?>

        <h2>Custom search</h2>
        <form method="get" action="#" class="form-horizontal">
            <div class="form-group">
                <label for="lat" class="control-label" >latitude</label>
                <input type="text" id="lat" name="lat" class="form-control input-lg" value="<?php echo $set_lat; ?>" />
            </div>
            <div class="form-group">
                <label for="long" class="control-label" >longitude</label>
                <input type="text" id="long" name="long" class="form-control input-lg" value="<?php echo $set_long; ?>" />
            </div>
            <div class="form-group">
                <label for="submit" class="control-label">search</label>
                <input type="submit" class="form-control input-lg" id="submit" value="Search" />
            </div>
        </form>

        <h2>Result</h2>
        <form action="#" class="form-horizontal">
            <div class="form-group">
                <label for="coordinates">Result coordinates dataset</label>
                <textarea rows="40" cols="100" class="form-control input-lg" name="coordinates"><?php echo $output; ?></textarea>
            </div>
            <div class="form-group">
                <label for="debug_info">Debug information</label>
                <textarea rows="40" cols="100" class="form-control input-lg" name="debug_info"><?php echo $debug_info; ?></textarea>
            </div>
        </form>

        <h2>Re-search</h2>
        <form action="#" method="get" class="form-horizontal">
            <div class="form-group">
            <label for="max_id" class="control-label">max_id</label>
            <input type="text" class="form-control input-lg" name="max_id" id="max_id" value="<?php echo $oldest_id; ?>" />
        </div>
        <div class="form-group">
            <label for="submit" class="control-label">search</label>
            <input type="submit" class="form-control input-lg" value="Search" />
        </div>
        </form>
        <p><a href="direct_input.php">input page</a></p>
    </div>
</body>
</html>

人に見せることを目的としていないコードなので本当に適当ですが、一応自分の中では使いやすいように色々とカスタムしてあります。このプログラムを順次走らせていくことで、ライブ期間中の全ツイートを調べることが出来ます。

データを整理する

上記のプログラムで収集した座標のデータセットは大量の重複を含んでいて、そのままのデータを地図にプロットすると閲覧するのにちょっと不便です。なので、重複データを排除するためにExcelで整理します。
適当に集めたJSON形式のデータをExcelに打ち込んでいきます。(改行挟んだりの整形はPHP使うと便利です。)

ワンクリックで重複削除できるんですね。便利!整理したデータを再びJSONにして、次はいよいよ地図にプロットしていきます。

地図にプロット

今回はGoogleが公開している Maps JavaScript API を使っていきたいと思います。APIの使い方のページに記載されている方法で自分用のAPIキーを取得します。そして、以下のようなページを作成して、いざプロットしていきます。

<!DOCTYPE html>
<html lang="ja">
<head>
    <title>Twitter trace</title>
    <meta charset="UTF-8" />
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Cache-Control" content="no-cache" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="index.css" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
        <script>
        var map;
        var marker = [];
        var infoWindow = [];
        var markerData = [
            {lat:35.768575,lng:139.420501},
            {lat:35.768493,lng:139.420522},
            {lat:35.77059347,lng:139.4194273},
            {lat:35.7707,lng:139.4198},
            {lat:35.76880072,lng:139.4209541},
            {lat:35.76879838,lng:139.4209604},
            {lat:35.7112046,lng:139.4640989},
            {lat:35.77136271,lng:139.4202191},
            {lat:35.8353742,lng:139.6503192},
            {lat:35.83783604,lng:139.6495825},
            {lat:35.76880259,lng:139.4209549},
            {lat:35.76946619,lng:139.4382386}
        ];
        function initMap() {
            var mapLatLng = new google.maps.LatLng({lat: markerData[0]['lat'], lng: markerData[0]['lng']});
            map = new google.maps.Map(document.getElementById('result_map'), {
                center: mapLatLng,
                zoom: 15
            });
            for (var i = 0; i < markerData.length; i++) {
                markerLatLng = new google.maps.LatLng({lat: markerData[i]['lat'], lng: markerData[i]['lng']});
                marker[i] = new google.maps.Marker({
                    position: markerLatLng,
                    map: map
                });
            }
        }
        </script>

        <div id="result_map"></div>

        <script async defer
        src="https://maps.googleapis.com/maps/api/js?key=*************************************&callback=initMap">
        </script>
    </div>
</body>
</html>

これだけで好きなだけ地図に地点をプロットできるなんて凄いですね。

まとめ

今回は最終的に8,000件くらいのツイートを収集して2,405件のユニークなデータを取得しました。このデータに関しては、誰でも簡単に閲覧することができるように公開してありますので、参考までに見てみてください。
データ閲覧

日本国内でも北は北海道、南は鹿児島県(確認できた中で最南端)から、世界にまで目を向けると上海やシンガポールなどからも来ていることが分かりました。こんなにも津々浦々から人々を呼び寄せることができるなんてラブライブ凄いなぁ、と言った感じです。

(ライブの)感想

初披露の曲や衣装やダンスを拝めて本当に素晴らしかった!初めてライブを見たんですけど、楽しすぎる…!というかキャスト同士にイチャつきが尊すぎる!!!!!もっと見たかった、というか2日目も参戦したかった!
次はファンミーティングや3rdツアーなどが予定されていますので、こちらの方はぜひ現地で参戦したいですね。

Twitter上のツイートを利用した日本語学習(第二弾)

標準

前回1000万ツイート程を収集した上での日本語学習を実施しましたが、今回は更に倍にして2000万ツイートにしてみましたので、それを詳しくまとめていきます。

準備段階

今回は自作のPHPプログラムを使いまして、2062万4138ツイートを収集しました。前回は1161万2661ツイートでしたので、約2倍です。
これで日本語学習の精度は上がるのだろうか、精度は別問題にしてもどれくらい学習が変わるのか、これを今回は調べていきます。
準備段階は前回までの記事に全て纏まっていますので、そちらを参考にしていただくとして先に進んでいきます。また、このページの最後に実際に使った学習ファイルをダウンロード出来るようにしましたので、ご活用ください。(結構重いです)

ベクトル演算の結果

今回も例のごとく単語のベクトル演算をしてもらいました。参考とするために、前回と同じ演算です。早速見ていきましょう。

yoshipc@ubuntu:~/twitter/word2vec$ ./word-analogy tweets-train.bin
Enter three words (EXIT to break): 現在 地球 未来

Word: 現在  Position in vocabulary: 674

Word: 地球  Position in vocabulary: 3337

Word: 未来  Position in vocabulary: 1570

                                              Word              Distance
------------------------------------------------------------------------
                                            世界		0.603715
                                            人類		0.578384
                                            宇宙		0.550593
                                            現実		0.538544
                                            運命		0.516235
                                   明るい未来		0.514421
                                               空		0.510775
                                         この世		0.501839
                                            僕ら		0.501282
                                      希望の光		0.499918
                                         この街		0.493066
                                               夢		0.492678
                                            人間		0.489397
                                               道		0.489035
                                            太陽		0.487439
                                         きっと		0.486102
                                            永劫		0.480969
                                         セカイ		0.477885
                                         未来へ		0.475911
                                            生命		0.470979
                                            大地		0.469094
                                         生き方		0.466944
                                            叡智		0.463096
                                            きみ		0.462352
                                         侵略者		0.461892
                                            人生		0.459877
                                      君の笑顔		0.453077
                                            虚像		0.451170
                                               心		0.450787
                                            こと		0.447146
                                   大切なもの		0.447091
                                            道標		0.446497
                                         この国		0.446489
                                            遠く		0.445713
                                         大海原		0.445700
                                         地平線		0.445120
                                   ひとりでに		0.444735
                                            キミ		0.444560
                                         未来を		0.444312
                                      彼方から		0.444180


Enter three words (EXIT to break): 恐竜 噴火 人類

Word: 恐竜  Position in vocabulary: 14523

Word: 噴火  Position in vocabulary: 25009

Word: 人類  Position in vocabulary: 4424

                                              Word              Distance
------------------------------------------------------------------------
                                      日本国民		0.504782
                                      国際社会		0.498614
                                   放射能漏れ		0.486438
                                            瓦解		0.485425
                                            収束		0.477185
                                            国民		0.472936
                                      電源喪失		0.471543
                                            人民		0.465190
                                      政権交代		0.464547
                                         未曾有		0.464171
                                      日本民族		0.462117
                                            国家		0.450937
                                            滅亡		0.450119
                                            事象		0.449914
                                メルトダウン		0.447464
                                      われわれ		0.444761
                                            地球		0.444433
                                               瀕		0.441625
                                      日本政府		0.440596
                                            過ち		0.440204
                                   大東亜戦争		0.439783
                                            履行		0.437771
                                      原発事故		0.435660
                                            停戦		0.432246
                                            是認		0.431025
                                      敵国条項		0.430867
                                            直面		0.428798
                                            行使		0.427611
                                         中国軍		0.426728
                                            失政		0.426705
                                      武力行使		0.426567
                                         我が国		0.424916
                                      安倍政権		0.424625
                                      巨大地震		0.423229
                                            暴落		0.422987
                                            存在		0.422820
                                      金融危機		0.421636
                                            戦後		0.420972
                                            事態		0.419899
                                            戦没		0.419073

Enter three words (EXIT to break): 過去 戦争 未来

Word: 過去  Position in vocabulary: 1033

Word: 戦争  Position in vocabulary: 2559

Word: 未来  Position in vocabulary: 1570

                                              Word              Distance
------------------------------------------------------------------------
                                            平和		0.522789
                                            侵略		0.517995
                                            国家		0.517953
                                      民主主義		0.513909
                                            争い		0.508577
                                            独裁		0.508006
                                            恐慌		0.491936
                                            戦い		0.487261
                                            破滅		0.485378
                                      侵略戦争		0.484970
                                            革命		0.484187
                                            秩序		0.481204
                                            滅ぶ		0.479859
                                      日本侵略		0.476639
                                            圧政		0.475845
                                      世界平和		0.475404
                                      資本主義		0.475313
                             第三次世界大戦		0.475173
                                      社会主義		0.474103
                                            支配		0.473573
                                            中露		0.472770
                                            僕ら		0.472601
                                            我々		0.472268
                                   日本の農業		0.472103
                                         私たち		0.470849
                                      共産主義		0.468439
                                   新自由主義		0.466063
                                   ニヒリズム		0.465786
                                               国		0.465224
                                         核戦争		0.465120
                                            滅亡		0.464730
                                            闘い		0.464701
                                   明るい未来		0.464211
                                      保護主義		0.462045
                                            紛争		0.459765
                                            滅び		0.458792
                                            鎖国		0.456679
                                         為政者		0.455943
                                      全体主義		0.455139
                                            反乱		0.454954


Enter three words (EXIT to break): 現在 核戦争 未来 

Word: 現在  Position in vocabulary: 674

Word: 核戦争  Position in vocabulary: 69314

Word: 未来  Position in vocabulary: 1570

                                              Word              Distance
------------------------------------------------------------------------
                                            戦争		0.569488
                                            現実		0.550737
                                      人類滅亡		0.528336
                                            破滅		0.518106
                                      保護主義		0.512427
                                            滅ぶ		0.503720
                                      全体主義		0.494948
                                            運命		0.493296
                                            滅び		0.492078
                                      世界平和		0.489570
                             第三次世界大戦		0.489473
                                      民主主義		0.488292
                                            平和		0.487700
                                      共産主義		0.483427
                             ナショナリズム		0.482726
                                   明るい未来		0.482302
                                      社会主義		0.481790
                                            独裁		0.479569
                                            人類		0.475583
                                      世界恐慌		0.469627
                                            恐慌		0.469290
                                   ファシズム		0.469131
                                ポピュリズム		0.467034
                                            中露		0.466852
                                            侵略		0.466768
                                         未来を		0.466476
                                      独裁国家		0.466271
                                            災い		0.465553
                                            専制		0.464848
                                            滅亡		0.464760
                                            永劫		0.462897
                                            こと		0.462651
                                            無力		0.461402
                                         権力者		0.459051
                                            災厄		0.459035
                                            虚像		0.457459
                                トランプ政権		0.457113
                                      侵略戦争		0.454696
                                            政権		0.454047
                                            それ		0.453413


Enter three words (EXIT to break): 女性 かわいい 男性

Word: 女性  Position in vocabulary: 492

Word: かわいい  Position in vocabulary: 275

Word: 男性  Position in vocabulary: 841

                                              Word              Distance
------------------------------------------------------------------------
                                         可愛い		0.888274
                                      カワイイ		0.761770
                                   かっこいい		0.757136
                                      かわゆい		0.748681
                                   かわいいよ		0.730760
                                      かわいー		0.703242
                                      可愛い〜		0.691793
                                   カッコイイ		0.671846
                                   かわいかっ		0.653079
                                      可愛かっ		0.652575
                                            すき		0.645260
                                   かわいい〜		0.639327
                                      可愛いい		0.631806
                                      可愛いー		0.631314
                                         萌える		0.616470
                                         似合う		0.616324
                                      格好いい		0.607348
                                      かわいく		0.593961
                                   可愛らしい		0.580756
                                   かわいい~		0.576812
                                         可愛く		0.575392
                                      あざとい		0.572130
                                      めんこい		0.571543
                                   かわいいー		0.571391
                                かわいらしい		0.566938
                                         ずるい		0.565993
                                   かわいいっ		0.565969
                                      かわいっ		0.565026
                                   愛くるしい		0.558229
                                      かわいぃ		0.557168
                                   ちっちゃい		0.549026
                                      可愛いっ		0.547052
                                         かわい		0.545649
                                      色っぽい		0.545449
                                   おもしろい		0.543379
                                            可愛		0.543249
                                      かわゆし		0.543152
                                      かわい〜		0.538648
                                      可愛いぃ		0.537529
                                      可愛い~		0.536874

ちょっと良くわからないので、前回の結果と比較してみます。

着色は両方の演算結果に登場した単語です。一見すると1000万ツイート分の結果を濃縮したのが2000万ツイート分の結果という感じな気がします。これを何か数字で傾向を算出出来れば良いのですが、このような分野には疎いものでよくわかりません。何か良い手段が有りましたら、コメントなどでお知らせください。

また、「恐竜 噴火 人類」の演算結果ではなぜか原発系の用語が殆どなくなりました。他にも色々な変化が見られました。やっぱり日本語モデルを2倍にするだけでも変化はあるんですね。次は関連語出力です。

関連語出力

早速見ていきます。

yoshipc@ubuntu:~/twitter/word2vec$ ./distance tweets-train.bin
Enter word or sentence (EXIT to break): トランプ

Word: トランプ  Position in vocabulary: 661

                                              Word       Cosine distance
------------------------------------------------------------------------
                                   トランプ氏		0.843974
                                      ヒラリー		0.814557
                                   クリントン		0.773175
                       ドナルド・トランプ		0.709894
                             トランプ大統領		0.706651
                    ヒラリー・クリントン		0.685431
                       トランプ次期大統領		0.674865
                                         民主党		0.671567
                                   次期大統領		0.660402
                    バーニー・サンダース		0.657438
                                      対立候補		0.646014
                                      アメリカ		0.640917
                          ドゥテルテ大統領		0.636720
                          リベラルメディア		0.635047
                                      極右政党		0.634951
                                      ネオコン		0.632521
                                   アメリカ人		0.632108
                                         共和党		0.631699
                                      副大統領		0.631480
                                            選挙		0.628310
                 エスタブリッシュメント		0.627984
                                      リベラル		0.626295
                          ドナルドトランプ		0.625530
                                         選挙後		0.624006
                                   ウォール街		0.622957
                                クリントン氏		0.621994
                                      選挙結果		0.615811
                                   オハイオ州		0.615090
                                            米国		0.614540
                                         大統領		0.613802
                                         アサド		0.610111
                                   大統領選挙		0.608435
                                         オバマ		0.607592
                                         安倍氏		0.604816
                          反グローバリズム		0.604310
                                   ネタニヤフ		0.602129
                                ポピュリスト		0.601324
                                         選挙戦		0.601310
                                   ドゥテルテ		0.600674
                                         ルペン		0.599487

Enter word or sentence (EXIT to break): ハルヒ

Word: ハルヒ  Position in vocabulary: 23003

                                              Word       Cosine distance
------------------------------------------------------------------------
                                      ストパン		0.645798
                                      けいおん		0.638650
                                      とらドラ		0.636988
                                花咲くいろは		0.632872
                                   らき☆すた		0.628135
                                      シュタゲ		0.627787
                                      ギルクラ		0.617519
                                          TARITARI		0.612508
                                グレンラガン		0.612221
                                      まどマギ		0.610592
                                シンフォギア		0.608070
                                      らきすた		0.606560
                             のんのんびより		0.602893
                                      バカテス		0.602474
                                         SHIROBAKO		0.601572
                                         ギアス		0.596853
                                         化物語		0.596690
                                   けいおん!		0.589731
                             ハヤテのごとく		0.586546
                             リリカルなのは		0.584632
              ウィッチクラフトワークス		0.584533
                                         結界師		0.584402
                                      かんなぎ		0.579284
                                   キルラキル		0.578478
                                      リトバス		0.577740
                          ブラックラグーン		0.577532
                                      ひぐらし		0.572559
                                      バクマン		0.568581
                          エルフェンリート		0.567559
                                      クラナド		0.566878
                          涼宮ハルヒの憂鬱		0.566182
                          アクセルワールド		0.565847
                                      きんモザ		0.565820
                                カブトボーグ		0.563231
                          アルスラーン戦記		0.561105
                                      プリリズ		0.559184
                 ストライクウィッチーズ		0.558513
                     対魔導学園35試験小隊		0.558363
                                      これゾン		0.558080
                                生徒会の一存		0.557798

Enter word or sentence (EXIT to break): Twitter

Word: Twitter  Position in vocabulary: 583

                                              Word       Cosine distance
------------------------------------------------------------------------
                                   ツイッター		0.869226
                                           twitter		0.845602
                                タイムライン		0.690816
                                   ついったー		0.646548
                                          Facebook		0.642719
                                      インスタ		0.632823
                                               SNS		0.613419
                             フェイスブック		0.602303
                             Twitter		0.578967
                             インスタグラム		0.563292
                                          facebook		0.560759
                                              LINE		0.552092
                                   ツィッター		0.539288
                                         Instagram		0.533319
                                      ツイート		0.524300
                                         SNS		0.520925
                                                TL		0.514066
                                         ニコ動		0.505256
                                      ツイッタ		0.496323
                                カカオトーク		0.491717
                                         ネット		0.490409
                                      ネット上		0.486285
                                             Slack		0.485163
                                               sns		0.479989
                                   アカウント		0.478253
                                         カイブ		0.477760
                                プッシュ通知		0.473205
                                         スパム		0.464073
                                            TL		0.459924
                                            GitHub		0.458841
                                            reddit		0.458549
                                            通知		0.456949
                                ツイッター上		0.456893
                                            携帯		0.456676
                                         プロフ		0.454460
                                      スカイプ		0.454132
                                      ブラウザ		0.454094
                                   コメント欄		0.453342
                                            safari		0.452758
                                            Flickr		0.450859

こちらも、結果を見ただけではよく分かりませんので、別にまとめてみます。

サンプル数が2つしか無いのではっきりとしたことは言えませんが、終わった話題(=安定した話題)は1000万と2000万では入れ替わりがそう激しくありませんが、常に変動し続ける話題(=不安定な話題)は変化が大きいです。この不安定な話題の代表が「アニメ」であって、比較を見てからも分かるように安定した話題と比較すれば大きく結果が異なっているのが分かります。

考察

Twitterという常に変動する言葉の辞書を活用することで今回一番良くわかったのは「何の話題がHOTなのか」です。例えば、関連語出力でも顕著に出ましたが、大統領選挙は現在さほど話題にはなっていませんが、アニメは1年中放送しているものなので常に話題が変動していきます。このような変化を大きく影響を受けることがよく分かりました。これからは更に日本語を収集する手段を考えながら精度の高い日本語のモデルを作っていけたらと思います。続編をお楽しみに!(ちなみに1000万ツイート収集するのに低スペックのパソコンでは16日かかりました。2000万で1ヶ月ちょいです。)

日本語モデル(?)の頒布

“tweets-train.zip” をダウンロード tweets-train.zip – 184 回のダウンロード – 462 MB


こちらが2000万ツイート分の日本語モデルです。著作権等は放棄しますが、自作発言、二次配布、商用利用はお控えください。また、予期せぬタイミングで削除に至る可能性も有りますので、その点もご承知おきください。ご利用時になにかコメントいただけると励みになります。よろしくお願いします。

追記(2017/08/11):今日の出来事に触発されたので、もう一回、ツイート長期収集を再開します。

Twitter上のツイートを利用した日本語学習

標準

現状

前回作成したプログラムで1000万(正確には1161万2661)ツイートを収集し、人工知能の元になる日本語学習のモデルを作成しました。それを、前々回の手順に基づき、色々と加工して語彙の塊を作ったところまで話は進みます。過去の記事にそこら辺の工程は記してあるので、今回はその結果について考察していきます。

ベクトル演算の結果

前々回の手順と同じ演算をしてみました。結構結果が違うところからかなりの語彙の差が見られます。

yoshipc@ubuntu:~/twitter/word2vec$ ./word-analogy tweets-train.bin											
											
Enter three words (EXIT to break): 現在 地球 未来											
											
Word: 現在 Position in vocabulary: 646											
											
Word: 地球 Position in vocabulary: 3132											
											
Word: 未来 Position in vocabulary: 1494											
											
	Word			Distance							
------------------------------------------------------------------------											
	世界			0.602624							
	人類			0.543273							
	現実			0.514047							
	宇宙			0.512201							
	道標			0.508042							
	この世			0.50619							
	この街			0.491833							
	セカイ			0.489193							
	人生			0.477655							
	人間			0.476668							
	希望の光		0.473739							
	道			0.473478							
	真理			0.469095							
	明るい未来		0.468303							
	素晴らしい世界		0.466917							
	空			0.466508							
	僕ら			0.461174							
	世界平和		0.459152							
	新しい世界		0.455947							
	夢			0.454776							
	彼方			0.453812							
	海へ			0.451184							
	生き物			0.451023							
	この国			0.450765							
	運命			0.449973							
	きっと			0.448351							
	生き方			0.446492							
	叡智			0.445666							
	キミ			0.444632							
	恒星			0.443009							
	海の底			0.442617							
	命			0.441733							
	輪廻転生		0.44141							
	侵略者			0.441408							
	死地			0.44047							
	旅路			0.440278							
	きみ			0.439143							
	公転			0.437911							
	夜空			0.437558							
	君の笑顔		0.434687							
											
Enter three words (EXIT to break): 恐竜 噴火 人類											
											
Word: 恐竜 Position in vocabulary: 15061											
											
Word: 噴火 Position in vocabulary: 22118											
											
Word: 人類 Position in vocabulary: 4781											
											
	Word			Distance							
------------------------------------------------------------------------											
	原発事故		0.532098							
	電源喪失		0.513952							
	福島原発事故		0.464274							
	太平洋戦争		0.46328							
	ラニーニャ現象		0.462596							
	人民			0.4581							
	日本国民		0.45673							
	巨大地震		0.456336							
	金融危機		0.456008							
	国民			0.448911							
	それら			0.446807							
	政権交代		0.445388							
	立証			0.443767							
	滅亡			0.442781							
	放射能漏れ		0.442724							
	災害			0.44182							
	政府			0.440498							
	我が国			0.43956							
	収束			0.438271							
	先の大戦		0.435819							
	大地震			0.435565							
	原子力発電所		0.433285							
	核戦争			0.433225							
	日本国			0.432804							
	暴風			0.430495							
	われわれ		0.429471							
	事象			0.427713							
	内部被曝		0.427674							
	日本軍			0.427604							
	金融経済		0.427537							
	暴落			0.427348							
	領海			0.426493							
	経済成長		0.426488							
	死			0.426103							
	自然災害		0.425942							
	中性子			0.424873							
	植民地支配		0.424667							
	トリチウム		0.421269							
	空爆			0.419897							
	福島第一原発事故	0.419747							
											
Enter three words (EXIT to break): 過去 戦争 未来											
											
Word: 過去 Position in vocabulary: 993											
											
Word: 戦争 Position in vocabulary: 2402											
											
Word: 未来 Position in vocabulary: 1494											
											
	Word			Distance							
------------------------------------------------------------------------											
	国家			0.549469							
	世界平和		0.526436							
	侵略			0.501115							
	アメリカ		0.501084							
	滅亡			0.500169							
	平和			0.493855							
	国			0.493639							
	私たち			0.492099							
	社会主義		0.4897							
	徴兵制			0.487121							
	平和憲法		0.486578							
	繁栄			0.484626							
	徴兵			0.473956							
	自主防衛		0.473593							
	多国籍企業		0.472732							
	軍事力			0.470309							
	この国			0.469006							
	秩序			0.468887							
	変革			0.468756							
	独裁			0.468424							
	軍隊			0.467761							
	民主主義		0.467356							
	滅び			0.466891							
	戦い			0.466708							
	祖国			0.463552							
	抑止力			0.463028							
	将来			0.460826							
	主権			0.457991							
	争い			0.457877							
	滅びる			0.457405							
	現実			0.455699							
	侵略戦争		0.453849							
	超大国			0.453782							
	建国			0.451772							
	紛争			0.450906							
	核戦争			0.450699							
	世界の終わり		0.450622							
	存亡			0.449972							
	社会			0.449561							
	滅ぶ			0.448486							
											
Enter three words (EXIT to break): 現在 核戦争 未来											
											
Word: 現在 Position in vocabulary: 646											
											
Word: 核戦争 Position in vocabulary: 64386											
											
Word: 未来 Position in vocabulary: 1494											
											
	Word			Distance							
------------------------------------------------------------------------											
	現実			0.550296							
	戦争			0.54772							
	滅亡			0.523266							
	それ			0.496773							
	滅びる			0.496528							
	滅ぶ			0.494136							
	ナショナリズム		0.491946							
	第三次世界大戦		0.488057							
	人類			0.484206							
	ヒトラー		0.483821							
	世界平和		0.472263							
	トランプ政権		0.468622							
	抑止力			0.4675							
	グローバル化		0.466767							
	破滅			0.466432							
	戦後日本		0.466088							
	こと			0.465714							
	民主主義		0.45992							
	世界の終わり		0.45799							
	保護主義		0.457665							
	平和			0.454754							
	アメリカ		0.454483							
	社会主義		0.453954							
	この国			0.453771							
	大統領			0.453712							
	存亡			0.452943							
	属国			0.449028							
	変革			0.448101							
	滅び			0.447887							
	死			0.447346							
	人類滅亡		0.446758							
	民衆			0.445977							
	徴兵制			0.445856							
	道義			0.445382							
	祖国			0.444785							
	軍事力			0.444622							
	日米安保		0.443597							
	米軍撤退		0.443395							
	政権			0.443134							
	将来			0.442936							
											
Enter three words (EXIT to break): 女性 かわいい 男性											
											
Word: 女性 Position in vocabulary: 473											
											
Word: かわいい Position in vocabulary: 275											
											
Word: 男性 Position in vocabulary: 791											
											
	Word			Distance							
------------------------------------------------------------------------											
	可愛い			0.87939							
	かっこいい		0.749638							
	かわいいよ		0.717992							
	かわゆい		0.717315							
	カワイイ		0.703926							
	かわいー		0.67568							
	すき			0.639878							
	カッコイイ		0.637353							
	可愛いい		0.635035							
	可愛い〜		0.626606							
	かわいかっ		0.626206							
	可愛かっ		0.622716							
	似合う			0.614752							
	格好いい		0.614094							
	萌える			0.606998							
	可愛らしい		0.588543							
	かわいいっ		0.578027							
	めんこい		0.577494							
	かわいぃ		0.576739							
	かわいい〜		0.569993							
	色っぽい		0.566761							
	かわいく		0.564131							
	大人っぽい		0.562167							
	可愛く			0.560525							
	カワユイ		0.559427							
	可愛いっ		0.558375							
	可愛いー		0.554952							
	おもしろい		0.553673							
	かわいいー		0.55007							
	愛くるしい		0.550066							
	かわいい~		0.54409							
	かわい			0.538456							
	ずるい			0.537333							
	可愛			0.53668							
	可愛い~		0.532784							
	かっこいー		0.5314							
	だいすき		0.527381							
	推せる			0.527268							
	お似合い		0.522254							
	あざとい		0.520163

これが演算結果です。本当にTwitterの語彙を吸い取ったっていう感じの結果ですね。ただ、まだまだ的をいていないと判断できる単語がたくさん有ります。1000万ツイートでも全然足りないんですね。また、大分内容が傾いてしまっているのでこれもなんとか是正したいところです。

関連語出力

次に「○○といえば?」という問いかけに対する答えを見てみます。今回は独自調査です。

										
yoshipc@ubuntu:~/twitter/word2vec$ ./distance tweets-train.bin											
											
Enter word or sentence (EXIT to break): トランプ											
											
Word: トランプ Position in vocablary: 370											
											
	Word			distance							
------------------------------------------------------------------------											
	トランプ氏		0.835056							
	ヒラリー		0.796449							
	クリントン		0.76346							
	ドナルド・トランプ	0.692498							
	トランプ大統領		0.668313							
	民主党			0.654428							
	アメリカ		0.648574							
	選挙			0.626273							
	トランプ次期大統領	0.625419							
	ドナルドトランプ	0.620136							
	共和党			0.616822							
	安倍さん		0.612783							
	エスタブリッシュメント	0.612736							
	バーニー・サンダース	0.60968							
	ヒラリー・クリントン	0.608063							
	対立候補		0.60636							
	アメリカ人		0.60183							
	ネオコン		0.596834							
	リベラル		0.595705							
	クリントン氏		0.595669							
	野沢直子		0.592253							
	副大統領		0.589429							
	上院議員		0.58592							
	ヒトラー		0.584391							
	大統領			0.582424							
	木村太郎		0.581774							
	橋下徹			0.579314							
	選挙結果		0.579113							
	オバマ			0.576084							
	選挙戦			0.57552							
	朴槿恵			0.571346							
	次期大統領		0.570646							
	ドゥテルテ		0.567364							
	政治家			0.567204							
	安倍内閣		0.566789							
	副大統領候補		0.566509							
	米国			0.564193							
	ジュリアーニ		0.563054							
	極右			0.562501							
	ウォール街		0.562185							
											
Enter word or sentence (EXIT to break): ハルヒ											
											
Word: ハルヒ Position in vocablary: 29688											
											
	Word			distance							
------------------------------------------------------------------------											
	らき☆すた		0.654328							
	CLANNAD			0.651727							
	キルラキル		0.649461							
	生徒会の一存		0.643134							
	化物語			0.626379							
	男子高校生の日常	0.624848							
	とらドラ		0.621756							
	シャーマンキング	0.620102							
	ストパン		0.613385							
	シュタゲ		0.610245							
	ギルクラ		0.607969							
	バカテス		0.607291							
	けいおん!		0.604257							
	はがない		0.598865							
	禁書			0.597113							
	ノゲノラ		0.597092							
	生徒会役員共		0.59606							
	リリカルなのは		0.595046							
	あの花			0.59435							
	俺の妹がこんなに可愛いわけがない	0.593053							
	のんのんびより		0.592703							
	ヒカルの碁		0.590836							
	クラナド		0.589519							
	けいおん		0.586876							
	青エク			0.586024							
	らきすた		0.584302							
	ガンダム00		0.583822							
	スケダン		0.581918							
	絶園のテンペスト	0.578972							
	うまるちゃん		0.576911							
	俺妹			0.57667							
	物語シリーズ		0.575383							
	とらドラ!		0.569344							
	寄生獣			0.568773							
	スラダン		0.56851							
	るろ剣			0.568442							
	ゼロの使い魔		0.566373							
	バクマン		0.565495							
	監獄学園		0.564057							
	俺ガイル		0.563473							

ハルヒの結果に一切キャラクターの出力がなく、延々と他のアニメのタイトルを出力しています。うーん、といった感じです。また、アメリカ大統領選挙の時期にツイートを収集したので結構そこら辺の語彙に豊富に見えます。まだまだ語彙に偏りがあることがこちらでも分かりますね。

今後の展望

現在1000万ツイートでもこの語彙力の偏り様なので、現在更に1000万ツイートを収集し、合計で2000万ツイートにしようと再び収集をはじめました。近い内にまた続編を更新するのでお楽しみに。

PHPでTwitterのユーザー情報を取得する

標準

今回は、PHPでTwitterのユーザー情報を取得してみたいと思います。このユーザーの情報は内部ID(Twitterのシステム内部で定められている、一意のIDの事。このIDは変更することが出来ない。)や、スクリーンネーム、名前を始めとして、アカウント作成した日時などありとあらゆる情報を取得できます。こちらは非常に簡単に作成出来るので、早速作っていきます。

使用するライブラリ

今回も例のごとく abraham/twitteroauth を使っていきます。使い方の詳細は前章を御覧ください。

コード

今回はプロフィール情報としても特に重要だと考える一部の情報を呼び出し、列挙する方法について書いていきます。最終的にコードは以下のようになりました。

<?php
$connection=new TwitterOAuth($api_key, $api_secret, $access_token, $access_token_secret);
$user_data=$connection->get("users/show",["screen_name"=>$user_screen_name]);

echo "name: " . $user_data->name;
echo "screen name: @" . $user_data->screen_name;
echo "location: " . $user_data->location;
echo "description: " . $user_data->description;
echo "url: " . $user_data->entities->url->urls[0]->expanded_url;
if($user_data->protected) {echo "protected";} else {echo "unprotected";}
echo "followers: " . number_format($user_data->followers_count);
echo "follows: " . number_format($user_data->friends_count);
echo "listed: " . number_format($user_data->listed_count);
echo "created at: " . $user_data->created_at;
echo number_format($user_data->favourites_count) . " favs";
echo number_format($user_data->statuses_count) . " tweets";
echo "banner-image: " . $user_data->profile_banner_url;
echo "profile-image" . $user_data->profile_image_url;
if($user_data->following) {echo "have followed";} else {echo "haven't followed";}
if($user_data->follow_request_sent) {echo "haven't sent";} else {echo "have sent";}
?>

今回のコードでは2行目にTwitterに接続して、3行目にユーザー情報を取得しています。この時、ユーザーの情報がstdClassで返ってくるので、それを分解して表示させます。

今回このユーザー情報を取得するためにはusers/showからgetしていますが、この時引数として指定できるのは

  • user_id (必須): Twitterから与えられている一意のID
  • screen_name(必須): 見慣れた@に続くID
  • include_entities(任意): エンティティ(返ってくるデータにエンティティノードが存在する。詳しくは後述。)を含めるか

を指定できます。また、この場合user_idとscreen_nameの両方が必須となっていますが、実際にはどちらか一方を指定するのみで大丈夫です。

返ってくるデータ

実際にgetしてみた時のデータをvar_dump()で見てみるとこんな感じです。

object(stdClass)#3 (46) {
	["id"]=> int(2414640626)
	["id_str"]=> string(10) "2414640626"
	["name"]=> string(5) "yoooo"
	["screen_name"]=> string(9) "yoshi_pc_"
	["location"]=> string(12) "鹿屋基地"
	["profile_location"]=> NULL
	["description"]=> string(53) "長門主義(ハルヒ)/SCP財団職員/提督業"
	["url"]=> string(23) "https://t.co/MP3ew8X4mK"
	["entities"]=> object(stdClass)#8 (2) {
		["url"]=> object(stdClass)#9 (1) {
			["urls"]=> array(1) {
				[0]=> object(stdClass)#10 (4) {
					["url"]=> string(23) "https://t.co/MP3ew8X4mK"
					["expanded_url"]=> string(18) "https://yoshipc.net"
					["display_url"]=> string(11) "yoshipc.net"
					["indices"]=> array(2) {
						[0]=> int(0)
						[1]=> int(23)
					}
				}
			}
		}
		["description"]=> object(stdClass)#11 (1) {
			["urls"]=> array(0) { }
		}
	}
	["protected"]=> bool(false)
	["followers_count"]=> int(663)
	["friends_count"]=> int(812)
	["listed_count"]=> int(14)
	["created_at"]=> string(30) "Thu Mar 27 16:51:41 +0000 2014"
	["favourites_count"]=> int(42076)
	["utc_offset"]=> int(32400)
	["time_zone"]=> string(5) "Tokyo"
	["geo_enabled"]=> bool(true)
	["verified"]=> bool(false)
	["statuses_count"]=> int(99429)
	["lang"]=> string(2) "ja"
	["status"]=> object(stdClass)#12 (22) {
		["created_at"]=> string(30) "Tue Oct 18 10:54:24 +0000 2016"
		["id"]=> int(788332394625441792)
		["id_str"]=> string(18) "788332394625441792"
		["text"]=> string(21) "千葉県魔うまい"
		["truncated"]=> bool(false)
		["entities"]=> object(stdClass)#13 (4) {
			["hashtags"]=> array(0) { }
			["symbols"]=> array(0) { }
			["user_mentions"]=> array(0) { }
			["urls"]=> array(0) { }
		}
		["source"]=> string(63) "TheWorld Rev"
		["in_reply_to_status_id"]=> NULL
		["in_reply_to_status_id_str"]=> NULL
		["in_reply_to_user_id"]=> NULL
		["in_reply_to_user_id_str"]=> NULL
		["in_reply_to_screen_name"]=> NULL
		["geo"]=> NULL
		["coordinates"]=> NULL
		["place"]=> NULL
		["contributors"]=> NULL
		["is_quote_status"]=> bool(false)
		["retweet_count"]=> int(0)
		["favorite_count"]=> int(1)
		["favorited"]=> bool(false)
		["retweeted"]=> bool(false)
		["lang"]=> string(2) "ja"
	}
	["contributors_enabled"]=> bool(false)
	["is_translator"]=> bool(false)
	["is_translation_enabled"]=> bool(false)
	["profile_background_color"]=> string(6) "C0DEED"
	["profile_background_image_url"]=> string(78) "http://pbs.twimg.com/profile_background_images/602136959914418176/TWaUNkvB.jpg"
	["profile_background_image_url_https"]=> string(79) "https://pbs.twimg.com/profile_background_images/602136959914418176/TWaUNkvB.jpg"
	["profile_background_tile"]=> bool(true)
	["profile_image_url"]=> string(74) "http://pbs.twimg.com/profile_images/762332527734378496/AzzARkY3_normal.jpg"
	["profile_image_url_https"]=> string(75) "https://pbs.twimg.com/profile_images/762332527734378496/AzzARkY3_normal.jpg"
	["profile_banner_url"]=> string(59) "https://pbs.twimg.com/profile_banners/2414640626/1468929549"
	["profile_link_color"]=> string(6) "3B94D9"
	["profile_sidebar_border_color"]=> string(6) "000000"
	["profile_sidebar_fill_color"]=> string(6) "DDEEF6"
	["profile_text_color"]=> string(6) "333333"
	["profile_use_background_image"]=> bool(true)
	["has_extended_profile"]=> bool(true)
	["default_profile"]=> bool(false)
	["default_profile_image"]=> bool(false)
	["following"]=> bool(false)
	["follow_request_sent"]=> bool(false)
	["notifications"]=> bool(false)
	["translator_type"]=> string(7) "regular"
	["suspended"]=> bool(false)
	["needs_phone_verification"]=> bool(false)
}

これを使うだけでも十分なユーザープロフィール画面が作れそうですね。前述したエンティティを含めるか、と言うのは上記のデータの中で「entities」以下のハイライトされている部分を含めるかどうかということです。主にURLについてのデータなので、不要だと感じたのであれば拒否ることで(若干ですが)早い挙動を得ることが出来るでしょう。
実際に作ってみたサンプルがこちらです。

最後になりますが、実践としてクライアントを同時並行で制作しているので、お試しいただければ幸いです。
https://yoshipc.net/twitter/

では、次回をお楽しみに。

PHPでTwitterのタイムラインを取得する

標準

今回、色々な事情を鑑みてこのレンタルサーバーを利用してWebアプリという形態でTwitterクライアントを作成することにしました。Webクライアントの強みはどのプラットフォームでも動作可能など、強みがたくさんあるので、作る価値があるかもしれません。しかも、私の場合は例の「事情」もあるので尚更です。というわけでPHPを利用したTwitterのクライントを作っていくシリーズがこれより始まります。

利用するライブラリ

今回は abraham/twitteroauth というものを使っていきます。このライブラリはTwitterの一通りのAPIが実装されているので、私が目標とするクライアント作成にはもってこいです。

ダウンロードした後、autoload.phpを読み込ませることで利用できるようになります。(本来はcomposer.jsonを使って読み込ませるのが正規ルートです。)

$connection = new TwitterOAuth($api_key, $api_secret, $access_token, $access_token_secret);
$statuses = $connection->get("statuses/home_timeline", ["count" => 50]); //タイムラインを50ツイート取得
if(isset($statuses->errors)) {
  //エラー発生
  echo "some error occurred.";
  echo "error message: " . $statuses->errors[0]->message;
} else {
  //ツイートの取得に成功
  for ($i=0; $i < 49; $i++) {
    echo "profile image url: " . $statuses[$i]->user->profile_image_url;
    echo "user name: " . $statuses[$i]->user->name;
    echo "user's id: " . $statuses[$i]->user->screen_name;
    echo "tweet text: " . $statuses[$i]->text;
    echo "created at: " . $statuses[$i]->created_at;
    echo "via: " . $statuses[$i]->source;
    echo $statuses[$i]->retweet_count . " rt";
    echo $statuses[$i]->favorite_count . " fav";
    if($statuses[$i]->user->protected) {echo "非公開";}
    echo "-------------------------------"
    }
  }

1行目で取得済みの各キーでTwitterに接続するための前準備を行い、2行目でタイムラインを50ツイート分取得しています。この時、APIのレートリミットを超過したアクションを行うとerrors[]->messageにその内容が帰ってきます。(エラーコードなども取得できるので詳しくはvar_dumpなどを行ってください。)

8行目以降はツイート取得に成功した場合です。最小限で利用するような情報を引き抜いてみました。それぞれのツイートには、ツイートに関する情報が$statuses以下、投稿者に関する情報が$statuses->userにそれぞれ格納されています。

以下は、試しにたまたま流れてきたユーザーの$statuses(Array 配列だけではなく、stdClass オブジェクトでも構成されていることに注意。Arrayは$statuses[“hoge”]と指定するのに対して、オブジェクトは$statuses->hogeと指定。)をvar_dump()で出力してみた結果が以下です。

array(25) { 
	[0]=> object(stdClass)#3 (23) { 
		["created_at"]=> string(30) "Fri Oct 14 12:44:02 +0000 2016"
		["id"]=> int(786910433936420869)
		["id_str"]=> string(18) "786910433936420869"
		["text"]=> string(30) "コジィさん出るのかな"
		["truncated"]=> bool(false)
		["entities"]=> object(stdClass)#8 (4) {
			["hashtags"]=> array(0) { }
			["symbols"]=> array(0) { }
			["user_mentions"]=> array(0) { }
			["urls"]=> array(0) { }
		}
		["source"]=> string(81) "Twitter for iPad"
		["in_reply_to_status_id"]=> NULL
		["in_reply_to_status_id_str"]=> NULL
		["in_reply_to_user_id"]=> NULL
		["in_reply_to_user_id_str"]=> NULL
		["in_reply_to_screen_name"]=> NULL
		["user"]=> object(stdClass)#9 (41) {
			["id"]=> int(219588098)
			["id_str"]=> string(9) "219588098"
			["name"]=> string(9) "ふゆべ
			["screen_name"]=> string(11) "who_you_bee"
			["location"]=> string(0) ""
			["description"]=> string(64) "Tumblr:https://t.co/X4hF7e4Jvi Pixiv:https://t.co/8vCm4L63xm"
			["url"]=> string(23) "https://t.co/8vCm4L63xm"
			["entities"]=> object(stdClass)#10 (2) {
				["url"]=> object(stdClass)#11 (1) {
					["urls"]=> array(1) {
						[0]=> object(stdClass)#12 (4) {
							["url"]=> string(23) "https://t.co/8vCm4L63xm"
							["expanded_url"]=> string(27) "http://pixiv.me/savoiaxxs21"
							["display_url"]=> string(20) "pixiv.me/savoiaxxs21"
							["indices"]=> array(2) {
								[0]=> int(0)
								[1]=> int(23)
							}
						}
					}
				}
				["description"]=> object(stdClass)#13 (1) {
					["urls"]=> array(2) {
						[0]=> object(stdClass)#14 (4) {
							["url"]=> string(23) "https://t.co/X4hF7e4Jvi"
							["expanded_url"]=> string(26) "http://huyube21.tumblr.com"
							["display_url"]=> string(19) "huyube21.tumblr.com"
							["indices"]=> array(2) {
								[0]=> int(7)
								[1]=> int(30)
							}
						}
						[1]=> object(stdClass)#15 (4) {
							["url"]=> string(23) "https://t.co/8vCm4L63xm"
							["expanded_url"]=> string(27) "http://pixiv.me/savoiaxxs21"
							["display_url"]=> string(20) "pixiv.me/savoiaxxs21"
							["indices"]=> array(2) {
								[0]=> int(37)
								[1]=> int(60)
							}
						}
					}
				}
			}
			["protected"]=> bool(false)
			["followers_count"]=> int(8710)
			["friends_count"]=> int(668)
			["listed_count"]=> int(350)
			["created_at"]=> string(30) "Thu Nov 25 08:30:34 +0000 2010"
			["favourites_count"]=> int(15994)
			["utc_offset"]=> int(32400)
			["time_zone"]=> string(5) "Tokyo"
			["geo_enabled"]=> bool(false)
			["verified"]=> bool(false)
			["statuses_count"]=> int(96048)
			["lang"]=> string(2) "ja"
			["contributors_enabled"]=> bool(false)
			["is_translator"]=> bool(false)
			["is_translation_enabled"]=> bool(false)
			["profile_background_color"]=> string(6) "C0DEED"
			["profile_background_image_url"]=> string(79) "http://pbs.twimg.com/profile_background_images/488513744176037888/Jq1mlOeM.jpeg"
			["profile_background_image_url_https"]=> string(80) "https://pbs.twimg.com/profile_background_images/488513744176037888/Jq1mlOeM.jpeg"
			["profile_background_tile"]=> bool(true)
			["profile_image_url"]=> string(74) "http://pbs.twimg.com/profile_images/759076048420032512/nXPEc9QI_normal.jpg"
			["profile_image_url_https"]=> string(75) "https://pbs.twimg.com/profile_images/759076048420032512/nXPEc9QI_normal.jpg"
			["profile_banner_url"]=> string(58) "https://pbs.twimg.com/profile_banners/219588098/1471816404"
			["profile_link_color"]=> string(6) "ABB8C2"
			["profile_sidebar_border_color"]=> string(6) "FFFFFF"
			["profile_sidebar_fill_color"]=> string(6) "DDEEF6"
			["profile_text_color"]=> string(6) "333333"
			["profile_use_background_image"]=> bool(true)
			["has_extended_profile"]=> bool(false)
			["default_profile"]=> bool(false)
			["default_profile_image"]=> bool(false)
			["following"]=> bool(true)
			["follow_request_sent"]=> bool(false)
			["notifications"]=> bool(false)
		}
	["geo"]=> NULL
	["coordinates"]=> NULL
	["place"]=> NULL
	["contributors"]=> NULL
	["is_quote_status"]=> bool(false)
	["retweet_count"]=> int(0)
	["favorite_count"]=> int(0)
	["favorited"]=> bool(false)
	["retweeted"]=> bool(false)
	["lang"]=> string(2) "ja"
}

想像以上に情報が取得できていて、驚きです。これらの情報を使うことで、クライアントとしての道以外にも使い道が出来ると思うので、ぜひご活用ください。

また、実際にクライアントを作成している様子をこちらのサーバーで公開中なので、ぜひお試しいただければと。
https://yoshipc.net/twitter