概要

Twitter4JはTwitterが用意している様々なAPIを叩けるJavaのライブラリ。

本稿ではTwitter4jのSearchAPIStreamingAPIの2つを使って、Tweetを収集します。

収集することが目的なので、投稿とかタイムラインとかに関するAPIは扱いません。

@CretedDate 2012/02/07
@Versions Twitte4J 2.2.5

下記情報は古くなっているのでより新しい情報はこちらを参照

導入

公式サイトからjarを落としてクラスパスを通す。

Twitter4Jの公式サイト
http://twitter4j.org/ja/index.html

Mavenも利用できる。下記はセントラルリポジトリを利用した場合の記述。

      <dependency>
           <groupId>org.twitter4j</groupId>
           <artifactId>twitter4j-core</artifactId>
           <version>[2.2,)</version>
       </dependency>

セントタルレポジトリは遅れて反映される場合もあるので、確実に最新のを使いたい場合はhttp://twitter4j.org/maven2のレポジトリを見ると良いらしい。

JavaDocは下記。

Twitter4J JavaDoc
http://twitter4j.org/ja/javadoc/index.html

SearchAPIを使ってみる

SearchAPIはTweet本文に出現する単語を検索したり、投稿したユーザ名で検索したり、位置情報で検索したり等、いろいろできる。

まずは普通に単語を検索。

// 初期化
Twitter twitter = new TwitterFactory().getInstance();
Query query = new Query();

// 検索ワードをセット(試しにバルスを検索)
query.setQuery("バルス");

// 検索実行
QueryResult result = twitter.search(query);

System.out.println("ヒット数 : " + result.getTweets().size());

// 検索結果を見てみる
for (Tweet tweet : result.getTweets()) {
    // 本文
    System.out.println(tweet.getText());
    // 発言したユーザ
    System.out.println(tweet.getFromUser());
    // 発言した日時
    System.out.println(tweet.getCreatedAt());
    // 他、取れる値はJavaDoc参照
    // http://twitter4j.org/ja/javadoc/twitter4j/Tweet.html
}

サンプルコード全文

こんな感じでさらっと検索ができる。

ページングして検索してみる

デフォルトだと結果は15件しか取れないので、rpp(1回でに取得するTweet数)やpage(ページ番号)を指定してもっと取ってみる。

// 初期化
Twitter twitter = new TwitterFactory().getInstance();
Query query = new Query();

// 検索ワードをセット(試しにhttpを検索)
query.setQuery("http");

// 1度のリクエストで取得するTweetの数(100が最大)
query.setRpp(100);

// 最大1500件(15ページ)なので15回ループ
for (int i = 1; i <= 15; i++) {
    // ページ指定
    query.setPage(i);
    // 検索実行
    QueryResult result = twitter.search(query);
    // 取ったテキストを表示
    for (Tweet tweet : result.getTweets()) {
        System.out.println(tweet.getText());
    }
    // たまに次ページあるのに100件取れないことがあるから
    // 95件以上あったら次ページを確認しに行くことにする
    if (result.getTweets().size() < 95)
        break;
    // 連続でリクエストすると怒られるので3秒起きにしておく
    Thread.sleep(3000);
}

サンプルコード全文

これで最大1500件のTweetが取れる。「バルス」とか「あけおめ」みたいな音速で流れるTweetは追い切れないけど、任意のハッシュタグを監視するくらいならこれでいける。

日本語検索

日本語のTweetだけ検索したい場合は、QueryのsetLangでjaを指定する。

Twitterの言語判定機能はそれほど精度は良くないように見えるけど、日本語についてはだいたいちゃんとした結果が返ってくる。判定しやすい言語だしね。

// 日本語のhadoopに関するTweetを指定
Query query = new Query();
query.setQuery("hadoop");
query.setLang("ja");

サンプルコード全文

ユーザ検索

指定ユーザのTweetを検索したい場合は、fromやtoを用いる。

from:usernameで指定ユーザのTweetが取れる。

to:usernameで指定ユーザに対してリプライしているTweetが取れる。

// faridyuさんのTweetとfaridyuさんへのリプライを取得
Query query = new Query();
query.setQuery("from:faridyu OR to:faridyu");

サンプルコード全文

GeoLocationで検索

緯度と経度を指定して、その周辺のTweetを取ることができる。

下記の例は新宿区役所を中心に10km四方のTweetを検索した例。

// 初期化
Twitter twitter = new TwitterFactory().getInstance();
Query query = new Query();

// 緯度経度を使って新宿区役所あたりから10km四方を設定(IPアドレスでも指定できるらしい)
GeoLocation geo = new GeoLocation(35.69384, 139.703549);
query.setGeoCode(geo, 10.0, Query.KILOMETERS);

// 検索実行
QueryResult result = twitter.search(query);

// これで新宿らへんのTweetがとれてるらしい(placeやgeoLocationはほぼ空のようだけど)
for (Tweet tweet : result.getTweets()) {
    System.out.println(tweet.getText());
    System.out.println(tweet.getPlace() + " : " + tweet.getGeoLocation());
}

サンプルコード全文

見た感じ、GeoLcationが付加されていないTweetも取れてるみたいだけど何で検索してるんだろう。IPアドレスかな。

StreamingAPIの準備

StreamingAPIは、接続を繋ぎっぱなしにしてTwitterからランダムサンプリングされた新着Tweetを送ってもらう機能。

StreamingAPIに関する機能はTwitter4JのCoreには入っていないので、twitter4j-core.x.x.x.jar以外に、twitter4j-stream.x.x.x.jarをクラスパスに通す必要がある。

Maven利用の場合は以下をDependencyに追加する。

        <dependency>
            <groupId>org.twitter4j</groupId>
            <artifactId>twitter4j-stream</artifactId>
            <version>[2.2,)</version>
        </dependency>

StreamingAPIを利用する際はoAuthのキーとかが必要になるので、twitter developersでもらってくる。

twitter developers
https://dev.twitter.com/apps/new

取り方は下記のサイトが分かりやすかった。

とあるOAuthのtwitterクライアント
http://lab.klab.org/young/2010/06/%E3%81%A8%E3%81%82%E3%82%8Boauth%E3%81%AEtwitter%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88/

StreamingAPIのコード

準備ができたので次は実際のコードを。

Listenerを作って登録しておくと、Tweetを取得するたびにイベントが発生するような感じになっている。

xxxxxxxxxxxになってるところは、twitter developersで取得した情報で置き換えてください。

public class Streaming {

    public static void main(String[] args) {
        // 認証キーを設定
        ConfigurationBuilder builder = new ConfigurationBuilder();
        builder.setOAuthConsumerKey("xxxxxxxxxx");
        builder.setOAuthConsumerSecret("xxxxxxxxxx");
        builder.setOAuthAccessToken("xxxxxxxxxx");
        builder.setOAuthAccessTokenSecret("xxxxxxxxxx");

        // Configurationを作る
        Configuration conf = builder.build();

        // TwitterStreamのインスタンス作成
        TwitterStream twitterStream = new TwitterStreamFactory(conf).getInstance();

        // Listenerを登録
        twitterStream.addListener(new Listener());

        // 実行
        twitterStream.sample();
    }
}

/** Tweetを出力するだけのListener */
class Listener extends StatusAdapter {
    // Tweetを受け取るたびにこのメソッドが呼び出される
    public void onStatus(Status status) {
        System.out.println(status.getText());
    }
}

サンプルコード全文

実行するとものすごい勢いでTweetが流れていきます。

SearchAPIの時はTweetというクラスにTweetの情報が入っていたけど、StreamingではStatusというクラスに入っている。

Statusで取れる情報はJavaDoc参照。基本、Tweetより取れる情報は豊富。

Status JavaDoc
http://twitter4j.org/ja/javadoc/twitter4j/Status.html

補足

騙されやすい点として、SearchAPIで取れるgetFromUserId()とかgetToUserId()は、Statusで取れるuserIdとは別物だという罠があるそうな。

IDが欲しい場合はgetUserMentionEntities()から取得すれば正しいのが入っているとか。