ラブライブ!サンシャイン!!楽曲一覧

標準

なかなかネットで調べていて最新の情報が見つからないので、自分で作りました。間違えなどありましたら、コメントでお知らせください。
最新情報が発表され次第、更新していきます。情報量が多いので、横にスクロールできるようになっています。

→→→→ スクロール →→→→

曲名 発売日 備考 収録アルバム キャッチコピー センター
君のこころは輝いてるかい? 2015/10/07 1stシングル 君のこころは輝いてるかい? 高海千歌、桜内梨子 Aqours
Step! ZERO to ONE
Aqours☆HEROES
恋になりたいAQUARIUM 2016/04/27 2ndシングル 恋になりたいAQUARIUM 渡辺曜 Aqours
待ってて愛のうた
届かない星だとしても
元気全開DAY!DAY!DAY! 2016/05/11 1stミニユニットシングル 元気全開DAY!DAY!DAY! CYaRon!
夜空はなんでも知ってるの?
トリコリコPLEASE!! 2016/05/25 1stミニユニットシングル トリコリコPLEASE!! AZALEA
ときめき分類学
Strawberry Trapper 2016/06/08 1stミニユニットシングル Strawberry Trapper Guilty Kiss
Guilty Night, Guilty Kiss!
青空Jumping Heart 2016/07/20 1期アニメOP 青空Jumping Heart 高海千歌 Aqours
ハミングフレンド
決めたよHand in Hand 2016/08/03 1期1話挿入歌 決めたよHand in Hand
/ダイスキだったらダイジョウブ!
──手に手をとって行こう! 2年生 2年生
ダイスキだったらダイジョウブ! 1期3話挿入歌
ユメ語るよりユメ歌おう 2016/08/24 1期アニメED ユメ語るよりユメ歌おう 進む時だよ、あたらしい場所へ! Aqours
サンシャインぴっかぴか音頭
夢で夜空を照らしたい 2016/09/14 1期6話挿入歌 夢で夜空を照らしたい
/未熟DREAMER
歌ってみよういっしょにね! 1、2年生
未熟DREAMER 1期9話挿入歌 松浦果南 Aqours
Pops heartで踊るんだもん! 2016/09/27 Blu-ray第1期第1巻 Aqours オリジナルソングCD (1) Aqours
空も心も晴れるから 2016/10/26 Blu-ray第1期第2巻 Aqours オリジナルソングCD (2) 2年生
想いよひとつになれ 2016/11/09 1期11話挿入歌 想いよひとつになれ/MIRAI TICKET あこがれ抱きしめて次へ進むんだ! 高海千歌、渡辺曜 桜内梨子以外の8人
MIRAI TICKET 2016/11/09 1期13話挿入歌 Aqours
ジングルベルがとまらない 2016/11/23 スクフェスオリジナル ジングルベルがとまらない Aqoursのシャンシャン♪
Christmas♪
Aqours
聖なる日の祈り
Waku-Waku-Week! 2016/11/25 Blu-ray第1期第3巻 Aqours オリジナルソングCD (3) 1年生
2016/11/30 1期アニメOST Sailing to the Sunshine 輝きの欠片を集めて…
Daydream Warrior 2016/12/22 Blu-ray第1期第4巻 Aqours オリジナルソングCD (4) Aqours
G線上のシンデレラ 2017/01/27 Blu-ray第1期第5巻 Aqours オリジナルソングCD (5) 3年生
P.S.の向こう側 2017/02/16 Blu-ray第1期ゲーマーズ
全巻購入特典(日付は初出)
P.S.の向こう側 CYaRon!
LONELY TUNING Blu-ray第1期ソフマップ
全巻購入特典(日付は初出)
LONELY TUNING AZALEA
Guilty Eyes Fever Blu-ray第1期アニメイト
全巻購入特典(日付は初出)
Guilty Eyes Fever Guilty Kiss
スリリング・ワンウェイ 2017/02/24 Blu-ray第1期第6巻 Aqours オリジナルソングCD (6) Aqours
太陽を追いかけろ! 2017/03/24 Blu-ray第1期第7巻 Aqours オリジナルソングCD (7) Aqours
HAPPY PARTY TRAIN 2017/04/05 3rdシングル HAPPY PARTY TRAIN 松浦果南 Aqours
SKY JOURNEY
少女以上の恋がしたい
近未来ハッピーエンド 2017/05/10 2ndミニユニットシングル 近未来ハッピーエンド 近未来を選べ! CYaRon!
海岸通りで待ってるよ
GALAXY HidE and SeeK 2017/05/31 2ndミニユニットシングル GALAXY HidE and SeeK やけどするほど、危険な3人! AZALEA
INNOCENT BIRD
コワレヤスキ 2017/06/21 2ndミニユニットシングル コワレヤスキ 愛にとどめをさす! Guilty Kiss
Shadow gate to love
Landing action Yeah!! 2017/06/30 「Aqours NEXT Step! Project」
テーマ曲
Aqours CLUB CD SET Aqours
夏への扉 Never end ver. 2017/08/02 「ハリケーン・ブロッサム」 ラブライブ!サンシャイン!!
デュオトリオコレクションCD
VOL.1
桜内梨子、国木田花丸、小原鞠莉
真夏は誰のモノ? 「インフェルノ・フェニックス」 黒澤ダイヤ、黒澤ルビィ
地元愛♡満タン☆サマーライフ 「ユニコーン・ブリザード」 渡辺曜、津島善子
夏の終わりの雨音が 「トワイライト・タイガー」 高海千歌、松浦果南
未来の僕らは知ってるよ 2017/10/25 2期アニメOP 未来の僕らは知ってるよ 私たち、輝きたい! 高海千歌 Aqours
君の瞳を巡る冒険
勇気はどこに?君の胸に! 2017/11/15 2期アニメED 勇気はどこに?君の胸に! 夢は、消えない Aqours
“MY LIST” to you!
MY舞☆TONIGHT 2017/11/29 2期3話挿入歌 MY舞☆TONIGHT
/MIRACLE WAVE
Aqours
MIRACLE WAVE 2期6話挿入歌 高海千歌

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ツアーなどが予定されていますので、こちらの方はぜひ現地で参戦したいですね。