Twitter4JはTwitterが用意している様々なAPIを叩けるJavaのライブラリ。
本稿ではTwitter4jのSearchAPI、StreamingAPIの2つを使って、Tweetを収集します。
収集することが目的なので、投稿とかタイムラインとかに関するAPIは扱いません。
公式サイトから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は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");
緯度と経度を指定して、その周辺の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は、接続を繋ぎっぱなしにして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/
準備ができたので次は実際のコードを。
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()から取得すれば正しいのが入っているとか。