2008年6月24日火曜日

Processingでtwitterと http認証 (basic auth)

Processingをつかって、httpをしゃべらせることは難しくはない。ただ通信してページを取ってくるだけならば、loadStrings() の引数にURLを指定してやれば、自動的にJavaのURLクラスを使ってStringsの配列として格納できる。これをつかって、twitterのデータを読み込もうとおもったのだが、twitterではbasic authを使わなければ自分のfriends timelineを取り出すことが出来ない。そこで basic authを processingでやってる例をさがしたのだが、発見できなかったので生のjavaでのbasic authの方法をそのまま取り込んで実現してみた。

さまざまなページによると javaでのhttp認証では java.net.authenticator とjava.net.PasswordAuthentication の2つのクラスを使い、Authenticator クラスを継承した認証クラスを作ってハンドラを設定する、というのが正解らしい。つまり、以下のようなコードとなるわけだ。



import java.net.Authenticator;
import java.net.PasswordAuthentication;

//public
class BasicAuth extends java.net.Authenticator{
private String user;
private String pass;
public BasicAuth(String user, String pass)
{
this.user = user;
this.pass = pass;
}

protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user,pass.toCharArray());
}
}




このクラスの利用方法は、user名とpasswordを設定して作成したクラスのインスタンスを生成し、そのあとで、Authenticator の setDefaultを呼び出す。前処理としてこの作業を行うと以降の http通信で認証が必要とされる場合には設定した情報をベースに自動的に認証が行われる。これをそのまま、processingに追加して使った。Processingは基本的にjavaそのものなので、このような場合の拡張は非常に簡単ですばらしい。
本当はpackage化してライブラリとするといいのだろうがそれはまた今後の課題ということにしておこう。

さて、現実にtwitterの出力するXMLの解析には、simlpeMLというライブラリを使うことにした。simpleMLはdaniel shiffman(http://www.shiffman.net/) の開発したライブラリであり彼のページからダウンロードできる。loadStrings()を使うよりもよい点は、後で XMLライブラリを使ってエレメントを取り出すよりも簡単なことと thread をつかって非同期にhttpリクエストを発生させて、ページを取得できたときにイベントを発生させることが出来る点である。とくに後者は、一定時間ごとにページを取得して書き換えるような動作を行いたい場合には、非常に有効であろう。

timelineの twitterAPI呼び出しを行うにはBasic認証付きでAPIで定められたURLを呼びだせばよい。受信形式はいろいろ見比べた結果、後処理がもっともやりやすそうなRSS形式を指定した。これらをまとめるとコードは以下のようになる。あとは、数分おきにreloadをするとか、スクロールするとかのフィーチャーを盛り込めば、twitter viewerとしての機能は十分だろう。
ちなみに書き込みは post method が必要なのだが、こちらも processingで使えるモジュールはなさそうなのとすこし複雑な処理が必要そうなのでもう一工夫必要なようなので今後の課題としておこう。
動作させるためには、フォントを作成する必要がある。Processingのメニューから Tools-->Create Fontを選択すると次のような画面が出るので Osakaフォントの16pointを指定する。日本語表示には日本語のフォントも必要なので All Fontのチェックボックスにもチェックをいれておく必要があるだろう。こうやってフォントを作成した後、コードの中の user と pass を自分のものに入れ替えれば動作させてみることができる。



--------------------------------
import simpleML.*;

import java.net.Authenticator;
import java.net.PasswordAuthentication;

// configration
String user = "uname" ;
String pass = "xxxxx" ;

// request url
String url = "http://twitter.com/statuses/friends_timeline.rss" ;

//public
class BasicAuth extends java.net.Authenticator{
private String user;
private String pass;
public BasicAuth(String user, String pass)
{
this.user = user;
this.pass = pass;
}

protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user,pass.toCharArray());
}

}


XMLRequest xmlRequest;

void setup() {
size(screen.width/2,screen.height/2);


BasicAuth tw_authenticator = new BasicAuth(user, pass);
Authenticator.setDefault(tw_authenticator);

// Creating and starting the request

xmlRequest = new XMLRequest(this,url);
xmlRequest.makeRequest();
}

void draw() {
// background(frameCount % 255);

}

// When the request is complete
void netEvent(XMLRequest ml) {

PFont fontA = loadFont("Osaka-16.vlw");
textFont(fontA, 16);

// Retrieving an array of all XML elements inside "" tags
String[] titles = ml.getElementArray("title");

for (int i = 0; i < titles.length ; i++) {
println(titles[i].replaceAll("\n",""));
fill(10*i,0,0) ;
text( titles[i].replaceAll("\n",""),5,18*(i+1)) ;
}

}

--------------------------------


ここまで。

1 件のコメント:

satakawo さんのコメント...

とても参考にさせていただきました。ありがとうございます。

二つ目(SimpleMLを使用している方)のプログラムでは、20個以上のメッセージは表示できないのでしょうか?

また、特定の語句が書かれたツイートを表示する事はできないでしょうか?

不勉強だとおっしゃるかもしれませんが、教えていただきたいです!