2014年10月21日火曜日

Processing + Twitter4j でタイムラインを取得&表示してみる - その3

気がついたら秋。毎度のことながら、かなりご無沙汰してました。教育実習(1ヶ月)もなんとか乗りきり、プログラムにさわって遊ぶ時間が取れるようになったので、ぼちぼちと勉強のメモを再開していきます。

前回のエントリでは、text() で長文を描画するとウィンドウに収まりきらないという問題を残したままになっていました。そこで今回は、GUI を使ってきれいにTwitter のタイムラインを表示させてみたいと思います。

  • controlP5 のインポート

controlP5 というGUI ライブラリのお世話になります。jar ファイルをプロジェクトの中のcode フォルダに入れます。twitter4j のjar ファイルが置いてあるのと同じ場所ですね。

controlP5 のライブラリを扱うために、新しく変数を宣言しています。カンタンです。

  • setup() 関数


ここでも大きな変更はありません。先ほど宣言した変数のcp5 にオブジェクトを代入する部分を加えるだけですね。

  • keyPressed() 関数:処理の呼び出し


いずれかのキーを押したときに、タイムラインからツイートを取得するためのgetTimeline() 関数を、5回呼び出します。これで、最新の上位5つを取ってきます。

  • getTimeline() 関数:ツイートの表示


今回のメインといえる部分です。ループ回数を引数として受け取っています。

controlP5 オブジェクトを使って、テキストエリアをつくります。テキストエリアは固有の名前をもつみたいなので、ループ回数を利用して違うラベリングをしましょう。その後ろにツイート内容を取得するための処理を書きます。最後にテキストエリアの位置とサイズを指定します。
テキストエリアの背景や文字の色なども変更できます。フォントはMeiryo やMS-Gothic を使わないと、日本語は文字化けしますよ。テキストエリアについての詳しい情報は、Textarea を見てください。

  • すべてのコード


これでツイートをフレームアウトさせることなく、きれいに表示させることができます。注意していただきたいのは、ツイートを取得するためのリクエスト数に制限が設けられているらしく、あまり頻繁にアクセスすると一定時間は応答がなくなるということです。詳しくは、API Rate Limits を読んでください。

またキーを2回押すと、同じ名前のテキストエリアがつくられてしまって、コンソールにエラーが表示されます(ツイートは正しく表示されるけど)。なので、更新ボタンなどのGUI を加えていく場合は、一度テキストエリアを消去してつくり直すような処理にしないとダメかもしれません。

以下のページを参考にさせていただきました。では、ごきげんよう。
  1. Processing Library
  2. controlP5 Examples

2014年7月23日水曜日

Processing + Twitter4j でタイムラインを取得&表示してみる - その2

お待たせしました。今回はいろいろ寄り道をしたいので、前置きはせずさっそくコードを見ていきましょう。

  • getTimeline() 関数:コンソールに表示


void getTimeline(){

  try{
    statuses = twitter.getHomeTimeline();

    for(Status status : statuses){
      println(status.getUser().getName() + "\n" +
              status.getText());
    }
  }

  catch(TwitterException e){
    println(" Get timeline: " + e +
            " Status code: " + e.getStatusCode());
  }
}

たったこれだけ。まず、初めで宣言したコレクションに、Twitter から取ってきたTL の情報を代入します。その後for-each ループで、それぞれのオブジェクトについてユーザー名とツイートの内容を取得して、表示させています。例外時の処理も書かないといけないので、try-catch 構造を使います。これを実行すると、最新のツイートの上位20個がコンソールに表示されると思います。


  • getTimeline() 関数:テキストとして表示


でもね、せっかくウィンドウを作ったんだから、やっぱりそこにtext() を使ってTL を表示させたい。そういう訳で、上のコードを少し変更してみましょう。

void getTimeline(){

  int i = 1;

  try{
    statuses = twitter.getHomeTimeline();

    for(Status status : statuses){
      text(status.getUser().getName() + "\n" +
           status.getText(), 30, 40*i);
      i++;
    }
  }

  catch(TwitterException e){
    println(" Get timeline: " + e +
            " Status code: " + e.getStatusCode());
  }
}

int 型の変数を用意したのは、それぞれのオブジェクトごとにツイートの表示位置を変えるためです。text() では文字情報だけでなく、x, y の位置情報も引数として渡してあげなくてはなりません。なので、オブジェクトを処理するたびに1を加算してy 座標を変更することで、取得したツイートを縦に並べて表示できるようにしています。


  • おい、ところでfor-each ループって何だよ


ぐぬぬ・・・、気付かれないようサラッとやり過ごすつもりだったけど、やっぱりバレたか。コレね、実はぼくもよく分かっていない。小難しい英語のドキュメントなんか読んでも、分からないものは分からない。とりあえず、今回のプログラムに沿って書き換えてみました。

/** for-each ループを使ってコンソールにTL を表示 **/

statuses = twitter.getHomeTimeline();

for(Status status : statuses){
  println(status.getUser().getName() + "\n" + status.getText());
}


/** ふつうのfor ループに置き換えてコンソールにTL を表示 **/

statuses = twitter.getHomeTimeline();

for(int i = 0; i < 20; i++) {
  println(statuses.get(i).getUser().getName() + "\n" +
          statuses.get(i).getText());
}

これがfor-each ループとふつうのfor ループの書き換えのようです。後者では、コレクションの中で何番目のオブジェクトかを指定する添字を使って、get() により毎回それを引っぱってくる必要があります。この処理を簡略化したものがfor-each ループだということで、この問題は解決とさせて下さい(やっぱり逃げた)。

  • すべてのコード


Twitter のTL から最新のツイートを5つ取得して、テキストとしてウィンドウに表示するプログラムです。20個だとちょっと多いので、サンプルとして必要最低限の数ってことで。for-each ループではなく、ふつうのfor を使って書いていたものです。

import twitter4j.conf.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.api.*;
import java.util.*;

String consumerKey = "xxxxx";
String consumerSecret = "xxxxx";
String accessToken = "xxxxx";
String accessSecret = "xxxxx";

Twitter twitter;
List<Status> statuses = null;

void setup(){

  size(480, 320);
  background(0);

  ConfigurationBuilder cb = new ConfigurationBuilder();
  cb.setOAuthConsumerKey(consumerKey);
  cb.setOAuthConsumerSecret(consumerSecret);
  cb.setOAuthAccessToken(accessToken);
  cb.setOAuthAccessTokenSecret(accessSecret);

  TwitterFactory tf = new TwitterFactory(cb.build());
  twitter = tf.getInstance();
}

void draw(){

}

void keyPressed(){
  getTimeline();
}

void getTimeline(){

  try{
    statuses = twitter.getHomeTimeline();

    for(int i = 0; i < 5; i++){
      text(statuses.get(i).getUser().getName() + "\n" +
           statuses.get(i).getText(), 30, 40*(i+1));
    }
  }

  catch(TwitterException e){
    println(" Get timeline: " + e +
            " Status code: " + e.getStatusCode());
  }
}

こんなエントリを読んでいらっしゃる暇な皆さんお気づきだと思いますが、text() は自動で改行してくれないのでツイートが長くなってしまうと、文字がフレームアウトして読むことができません。GUI ライブラリなんかでもっと見栄えよく仕上げたいとも思ったのですが、勉強不足のせいもあって、まだ形にもできず・・・。ControlP5 っていうのが有名なサードパーティによるライブラリみたいなのですが、これは日本語の表示に対応していないみたいで、文字化けしてしまいました(対処法があるのかもしれないけど、見つけられなかった)。

こんなまとめサイトもあるので、これから少しずつ他のライブラリにも探りを入れていって、感想でも書ければなあ・・・と思います。参考にさせてページは、以下のとおりです。ほな、さいなら。

  1. Twitter4j コードサンプル
  2. Processing Forum : get the timeline from a user with twitter4j (英語)

2014年7月20日日曜日

Processing + twitter4j でタイムラインを取得&表示してみる - その1

気づいたら半年もブログを更新してませんでした。まあ、就活とか忙しかったからね・・・って自己完結したところで、今回もだらだらと独り言を書き留めていきたいと思います。

前回に引き続き、Processing + Twitter4j で遊んでいきますよ。作ってみるのは、Twitter のタイムラインを取得して画面に表示させるプログラムです。Java ではなく、Processing でこれを実装する解説がされた日本語のページって、意外と少ない。「つぶやく」方はけっこう充実してるのに。Processing そのものがJava に近くて、もはやコードをコピペすれば動くんじゃないかくらいの勢いなので、当然といえば当然かもしれないけど。なので今回は、そのニッチなところに踏み込んでいきます。

  • 準備

よく見るとTwitter4j のバージョンがかなり更新されてるので、以前に紹介したリンク先から持ってきたものではなく、今回は本家のTwitter4j のサイトからZip をダウンロードして使用します(これを書いてる今はVer.4.0.2)。jar ファイルを置く場所などは前と同じです。ソースコードであるpde ファイルがある場所にcode フォルダを作って、その中に入れるんでしたよね。忘れてしまった人はぐぐるなり、前々回の記事を参照してくださいね。

プログラムを新しく作る場合は、Twitter のDeveloper ページで改めてアプリの登録をし、いろんなkey を入手した方がいいと思います。

  • import と変数の宣言


import twitter4j.conf.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.api.*;
import java.util.*;

String consumerKey    = "xxxxx";
String consumerSecret = "xxxxx";
String accessToken    = "xxxxx";
String accessSecret   = "xxxxx";

Twitter twitter;
List<Status> statuses = null;

はじめの部分です。前回と違うところがありますが、そんなに大したものではないです。まず、setup 関数の中で行っていたkey の入力を簡単にするため、ここで変数にしています。そして、取得したTL の内容を格納するためのリストを宣言し、null で初期化しています。

  • setup() 関数


void setup(){

  size(480, 320);
  background(0);

  ConfigurationBuilder cb = new ConfigurationBuilder();
  cb.setOAuthConsumerKey(consumerKey);
  cb.setOAuthConsumerSecret(consumerSecret);
  cb.setOAuthAccessToken(accessToken);
  cb.setOAuthAccessTokenSecret(accessSecret);

  TwitterFactory tf = new TwitterFactory(cb.build());
  twitter = tf.getInstance();
}

ウィンドウサイズと背景色を指定します。それ以下の部分には変更なしです。Twitter のアカウントにアクセスしていろんな操作をできるようにするため、key を読み込ませたりしているものと思われます(ぶっちゃけ、よく分かっていない)。

  • draw(), keyPressed() 関数


void draw(){

}

void keyPressed(){
  getTimeline();
}

たったこれだけ。draw 関数には何も書きません。ここは「毎フレーム実行される処理」を指定する部分だからです。1秒間に30回もTwitter に情報を取りに行くなんてメモリの無駄ですからね。なので、何かのキーを押したときだけgetTimeline() の処理を実行するようにしています。

  • ここまでのコード


import twitter4j.conf.*;
import twitter4j.*;
import twitter4j.auth.*;
import twitter4j.api.*;
import java.util.*;

String consumerKey    = "xxxxx";
String consumerSecret = "xxxxx";
String accessToken    = "xxxxx";
String accessSecret   = "xxxxx";

Twitter twitter;
List<Status> statuses = null;

void setup(){

  size(480, 320);
  background(0);

  ConfigurationBuilder cb = new ConfigurationBuilder();
  cb.setOAuthConsumerKey(consumerKey);
  cb.setOAuthConsumerSecret(consumerSecret);
  cb.setOAuthAccessToken(accessToken);
  cb.setOAuthAccessTokenSecret(accessSecret);

  TwitterFactory tf = new TwitterFactory(cb.build());
  twitter = tf.getInstance();
}

void draw(){

}

void keyPressed(){
  getTimeline();
}


void getTimeline(){

  /** 次回のエントリで作っていきます **/

}

getTimeline() が今回のプログラムで一番大事な部分になります。その詳しい内容とコードは、次回の記事で見ていくことにしましょう。遅くなりましたが、Processing のバージョンは2.2.1 です。参考にさせていただいたページは以下のとおりです。
  1. Processing2.0 とTwitter4Jで、Processing からTweet してみる