読者です 読者をやめる 読者になる 読者になる

Challenge Java EE !

Java EEを中心に趣味や仕事における開発メモを書いています。

Twitter4Jでエバスクのツイートを分析してみた #evatfm

雑記 Twitter4J

昔、乃木坂46公式Twitterアカウントのつぶやきを見ていて「最近一番多くRTされたツイートってどんなのだろう?」と思ったことがありました。で、当時Java EEとTwitter4Jの勉強兼ねてリツイート数とファボ(いいね)数が確認できる以下Webアプリを趣味開発して公開してました。

http://46collection.sakamichi46.com/
http://cdn-ak.f.st-hatena.com/images/fotolife/k/kikutaro777/20160313/20160313235434.jpg

で、最近ラジオ「エバンジェリストスクール! - TOKYO FM Podcasting」の公式ツイートみてて全く同じことを思ったり。

twitter.com

気になったので、(さすがにWebアプリではないのですが)Twitter4Jを利用して同じことを確認をしてみました。

※2017/2/14時点での集計ですので、実際には可変する可能性があります

コードはざっくりこんな感じ。ちょっと適当すぎかも(^^;

package com.sakamichi46.evatfm;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import twitter4j.Paging;
import twitter4j.ResponseList;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;

/**
 *
 * @author kikuta
 */
public class EvatfmAnalyticsMain {

    public static int MAX_PAGE = 200;
    public static int COUNT = 100;
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws TwitterException, InterruptedException, IOException {
        Twitter twitter = TwitterFactory.getSingleton();

        List<Status> count = count(twitter);
        List<Status> sortedByRetweet = count.stream().sorted(Comparator.comparing(Status::getRetweetCount).reversed()).collect(Collectors.toList());
        List<Status> sortedByFav = count.stream().sorted(Comparator.comparing(Status::getFavoriteCount).reversed()).collect(Collectors.toList());

        FileSystem fs = FileSystems.getDefault();
        Path path = fs.getPath("./evaRetweet.txt");
        try(BufferedWriter br = Files.newBufferedWriter(path, Charset.forName("UTF-8"))) {
            br.write(sortedByRetweet.toString());
            br.close();
        }

        path = fs.getPath("./evaFav.txt");
        try(BufferedWriter br = Files.newBufferedWriter(path, Charset.forName("UTF-8"))) {
            br.write(sortedByFav.toString());
            br.close();
        }
    }
    
    public static List<Status> count(Twitter twitter) {
        List<Status> listTimeline = new ArrayList<>();
        Paging page = new Paging(MAX_PAGE, COUNT);

        IntStream.range(1, MAX_PAGE).forEach(i -> {
            page.setPage(i);
            try {
                ResponseList<Status> userTimeline = twitter.getUserTimeline("@waki_evatfm", page);
                userTimeline.stream().forEach(s -> {
                    if(!listTimeline.contains(s)) {
                        listTimeline.add(s);
                    }
                });
            } catch (TwitterException ex) {
                System.out.println(ex);
            }
        });

        return listTimeline;
    }
}

いいね数

1位 545いいね


2位 376いいね


3位 368いいね


4位 334いいね


5位 331いいね


6位 303いいね


7位 301いいね


8位 263いいね


9位 262いいね


10位 252いいね


リツイート数

1位 216RT


2位 143RT


3位 140RT


4位 135RT


5位 133RT


5位 133RT


7位 126RT


8位 118RT


9位 115RT


10位 110RT

と、こんな感じで、全般的に若ちゃんの写真系が多い(^^;;;とはいえ、ある程度予想通りでしたがw

ちなみにエバスク公式ツイートではないですが、乃木坂46の公式アカウントがつぶやいた以下が、RT/Favともに多かったです。

ホントは #evatfm のハッシュタグを含むツイートの量を分析しようと思ったのですが、TwitterのSearch APIは2週間程度分くらいしか取得できないようで確認できませんでした。残念すぎる(*´Д`)(ちなみに2/10(金)~2/13(月)の間で調べたら3871件もありました!)

IT業界に身を置く自分としては、エバスクってホントにITのトレンド情報を流してるので、色々な豆知識ツイートをもっとRT/Favして欲しいなーとも(^^;

で、この分析してて思いついたのですが、趣味で作ってる若月さんのBotに「エバスク」とか「#evatfm」って話しかけたら@evatfmアカウントの過去ツイートをランダムに引っ掛けるような機能を実装しようかなーと思いました。

若様bot、なんだかんだで利用ユーザが100近くなっているので、エバスクリスナーな方々にも是非お試ししてもらいたいなーと思います。以下サイトが詳しいですが

wakasamabot.sakamichi46.com

こちらのQRコードをLINEのQRから読み取ってもらうと友達追加できます。

f:id:kikutaro777:20170128222526p:plain

それにしてもエバスクを聴けば聴くほど若ちゃんを好きになりますね。

f:id:kikutaro777:20170215001025j:plain

LINE Messaging APIで「若様bot」を作ってみました

Spring Boot Microsoft LINE Messaging API Heroku

なんだか今日は乃木坂46関連で色々とニュースが流れていて(ひめたん17th活動停止、まなったん写真集、文春砲…)大変な日です。

そんなニュースを横目に、コツコツとbotを作ってました。まだ開発途中なのですが、紹介ページも作ってみたので公開してみます(^^;

wakasamabot.sakamichi46.com

上記ページにもLINEで友だち追加するQRコードなどありますが、ここにも


f:id:kikutaro777:20170128222526p:plain:w200

LINEの友だち追加

このbotは、私が大好きな乃木坂46の若月佑美さんのAIと会話できるbotです。主には

  • 「若様」と話しかけるとブログなどの情報リンクを返してくれる
  • 「こんばんは」と話しかけると「こんばんわかつき~」と若ちゃん挨拶を返してくれる
  • 「写真」「画像」など話かけると若ちゃんの写真をランダムに送ってくれる


f:id:kikutaro777:20170125001539p:plain:w350

と、非常に俺得なbotとなっております。とはいえ当初目的は、若ちゃんの素晴らしさをもっと広めたい!という所ですので、もう少し一般的に楽しめる機能も少ないですが入れています。

  • 普通にトークできる機能(現状、文脈は取れないです)
  • 若ちゃんがやってるラジオ「エバンジェリストスクール」の「略語コーナー」再演


f:id:kikutaro777:20170125001600p:plain:w350

このブログみてくれる方は情報系学生さんやエンジニアの方が多いと思いますが、例えば「IBM」って何の略語かわかりますか(^^)?私はわかりませんでしたw ラジオでそういうやりとりをするコーナーがあるんですが、普段IT業界にいてもハっとさせられることが多いです。エバンジェリストスクール、略してエバスクに興味もった方は以下読んでみてください~。

kikutaro777.hatenablog.com

技術スタック的には

Bot

  • Heroku
  • Spring Boot
  • Cognitive Services(現状はBing Image Search API,QnA Maker)
  • DoCoMo 雑談対話 API

Web Site

などを利用しています。今後まだ機能拡張する予定で、Cognitive ServicesはもういくつかAPIを利用するつもりです。


現状、アイコンに若月さんの写真を使ってしまっているので、この辺は肖像権の話などありますので、変更していく予定です。せっかくなので、もう少し拡張して「LINE BOT AWARDS」に登録したいなぁと思っており、規約にもちゃんと以下明記されていましたので。

f:id:kikutaro777:20170128223252p:plain

こういうBotってどうしてもアイドルとかアニメなど、身近なネタと絡めたくなるので、こういう所が難しいですね(^^;もし、若ちゃんの似顔絵画像とか描きますよ!という方などいらっしゃったら、お声かけいただけると嬉しいです(>_<)

Spring BootとLINE Messaging APIで作ったLINE BOTをHerokuで動かす

Spring Boot LINE Messaging API Heroku

やっと触れましたLINE Messaging API。やばい、なにこれめっちゃ楽しい。

上のは完全に遊びですが、仕事でも真面目に検討してもいいのかもって今更ながら真面目に思い始めました。QRコードから簡単に友だち追加できるので、何かと初速が速いなぁと。とりあえずスマホだけあれば良いわけですし。と当たり前なことを今更言ってしまうぐらい楽しいです。

Javaな方々は公式からThe Messaging API SDK for Javaが出てるので、これで簡単に始められます。

github.com

ドキュメントは以下参照。

LINE API Reference

line-bot-spring-boot moduleもあるのでSpring Bootの勉強がてら始めるのもホントおすすめです(自分は完全にそんな感じ)

GitHubのページにサンプルコードありますが、単純に送ったメッセージをやまびこのようにブーメランするだけなら

package com.example.bot.spring.echo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.linecorp.bot.model.event.Event;
import com.linecorp.bot.model.event.MessageEvent;
import com.linecorp.bot.model.event.message.TextMessageContent;
import com.linecorp.bot.model.message.TextMessage;
import com.linecorp.bot.spring.boot.annotation.EventMapping;
import com.linecorp.bot.spring.boot.annotation.LineMessageHandler;

@SpringBootApplication
@LineMessageHandler
public class EchoApplication {
    public static void main(String[] args) {
        SpringApplication.run(EchoApplication.class, args);
    }

    @EventMapping
    public TextMessage handleTextMessageEvent(MessageEvent<TextMessageContent> event) {
        System.out.println("event: " + event);
        return new TextMessage(event.getMessage().getText());
    }

    @EventMapping
    public void handleDefaultMessageEvent(Event event) {
        System.out.println("event: " + event);
    }
}

で作れます。便利すぎる(^^;

誰でも簡単に、って感じなのだと思いますが、知ってると便利かなと思うことをまとめたいと思います。

クラウドとか使わずローカル環境で動作確認したいとき

当初、なんかサーバとかをクラウドに用意せんと動かせないよなーとか思ってたのですが、去年JJUG CCC 2016 FallでLINEの@tokuhiromさんがLINE BOT ライブコーディングをされていて、ngrokを使う方法を紹介されてました。

Java + spring-boot で書く! LINE BOT ライブコーディング。 · Issue #34 · jjug-ccc/call-for-paper-2016fall · GitHub

ngrokは知っていたので、これ聴いたとき、ぬおおー!その手があったのかって感じでした。(知ってたなら気づけっていう

ngrok.com

ngrok http 8080

と起動すればローカルPCの指定ポートを外部にトンネルしてくれます。

f:id:kikutaro777:20170116222625p:plain

Spring Bootでアプリを起動しておけば、上記ngrokでトンネルされたhttpとhttpsのURLをpublicに使うことできますので、httpsのアドレスをLINE Messaging APIに登録することができます。

f:id:kikutaro777:20170116222900p:plain

httpは以下のように登録できないので、ngrok使ったやり方は非常にお手軽だと思います。証明書もいらないし。

f:id:kikutaro777:20170116222942p:plain

設定まわり URLにcallback

Webhookを登録したとき、Verifyがうまくいかない、と最初ちょっとハマってました。Spring Boot利用したとき、デフォルトでは先ほどのキャプチャにあるように「https://hogehoge.ngrok.io/callback」のような形で「callback」と入れてあげる必要があります。GitHubのConfigurationに、デフォルトが「callback」になっていることが書いてあるのですが最初気づかなくて、ハマってました。

f:id:kikutaro777:20170116224349p:plain

あくまでデフォなので、変えてしまうのもありです。

設定まわり 自動応答メッセージ

ちゃんとドキュメント読めって感じなのですが、最初、WebhookのVerifyが成功してローカルPCにもデータ飛ぶのに、LINEから話かけると常に以下の「メッセージありがとうございます 申し訳ありませんが、このアカウントでは個別のご返信ができないのです 次回の配信をお楽しみに」と出てしまって、わからんーってなってました(^^;

f:id:kikutaro777:20170116223626j:plain

LINE@Managerで「アカウント設定」->「Bot設定」の「詳細設定」->「自動応答メッセージ」を「利用しない」にするだけです。

f:id:kikutaro777:20170116223907p:plain

herokuでhttps

ここまででローカル開発環境で色々遊べるのですが、最後はやっぱり公開してみたい、ということがあると思います。証明書は安いものを取るか、Let's Encryptなど使うか、など選択肢があるかと思いますが、それなりに手間だなぁと。で、探してたらHerokuのAdd-onでFixieを使うと簡単とのこと。

qiita.com

実際に試したらホント簡単でした(^^;

画像や動画、スタンプの認識

最後におまけですが、冒頭に出したサンプルコードはテキストメッセージをやまびこするものでしたが、画像とか動画、スタンプが送られてきた場合、どうフックするのかなーと思ったのですが、@EventMapping使って以下のように定義すれば、そのままフックされました。

@EventMapping
public Message handleStickerMessage(MessageEvent<StickerMessageContent> event) {
    return new TextMessage("スタンプ送信ありがとうございます!");
}
    
@EventMapping
public Message handleImageMessage(MessageEvent<ImageMessageContent> event) {
    return new TextMessage("画像送信ありがとうございます!");
}
    
@EventMapping
public Message handleVideoMessage(MessageEvent<VideoMessageContent> event) {
    return new TextMessage("動画送信ありがとうございます!");
}
    
@EventMapping
public Message handleAudioMessage(MessageEvent<AudioMessageContent> event) {
    return new TextMessage("音声送信ありがとうございます!");
}

@EventMapping
public Message handleFollowEvent(FollowEvent event) {
    return new TextMessage("友達追加ありがとうございます!");
}

Herokuの環境変数利用

LINEのChannelSecretやTokenはコードに埋め込んだり、設定ファイルでGitHubなどにアップするわけにはいかないので、Herokuなどでは環境変数を利用するのが良いかと思います。で、gradleを利用してる場合は

sample-spring-boot-echoのREADMEにあるように
github.com

../gradlew bootRun -Dline.bot.channelToken=YOUR_CHANNEL_TOKEN \
                   -Dline.bot.channelSecret=YOUR_CHANNEL_SECRET

みたいに指定するようです。自分はMaven使ってたのと、application.propertiesを上手く使えないかなぁと思って調べたら

line.bot.channelSecret = ${CHANNEL_SECRET}
line.bot.channelToken = ${CHANNEL_TOKEN}

というように定義することができました。ほえー便利。

ということで、Spring Bootの勉強を楽しみながらするのにもおススメなLINE Messaging APIでした!

すごい面白いのができたらAwardsに出して1000万狙うしかない!(無理

botawards.line.me