2011年10月5日水曜日

仕様変更に伴うTwitterStreamingReaderの変更

どうやら,Twitterで仕様変更があったらしく,
StreamingAPIを使ったデータの読み込みを変更しなければいけなくなりました.

具体的には,TwitterのDeveloper用ブログにあるとおり,
All our Streaming API products are now supporting SSL and we've just updated the Streaming API Methods, User Streams and Site Streams documentation pages accordingly. As we're planning to sunset HTTP support in about a month, we strongly encourage you to switch to SSL (HTTPS) as soon as possible, especially if you're still authenticating your Streaming API requests with Basic Auth.
ということで,SSLを使ってね,ということらしいです.

そんなわけで,以前作成したTwitterStreamReaderではなく,新しいバージョンを使ってください.

変更点は,SSLに対応させただけだけど.
得られるTweetデータはJSON形式なので,jsonicなどを使ってJSONの処理をちゃんとしないと日本語が文字化けするようです.
また,日本語のTweetだけ取り出したい人は,文字列に日本語が含まれるかどうかの判定をご参照ください.

package twitter;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * StreamAPIから送られてくるStreamデータをひたすら取得し続けるクラス
 * @author tori
 *
 */
public class TwitterStreamReader {


 /**
  * 使い方の例
  * @param args
  * @throws UnsupportedEncodingException 
  */
 public static void main(String[] args) throws UnsupportedEncodingException {
  
  TwitterStreamReader tsr = new TwitterStreamReader("Twitter-UserName", "Password");
  tsr.start();
  
  while(true){
   List<String> tweetList = tsr.readStoredList();
   List<String> errList = tsr.readErrLogList();
   
   for(String text:tweetList){
    System.out.println(text);
   }
   
   for(String err:errList){
    System.err.println(err);
   }
  }
 }
 
 /**
  * sampleのタイムライン取得のためのURL
  */
 private static final String DEFAULT_API_URL = "https://stream.twitter.com/1/statuses/sample.json";

 String userName;
 String password;

 /**
  * 強制終了させられたかどうか
  */
 boolean isForceStop;

 /**
  * 取得しているかどうか
  */
 boolean isRunning;
 
 /**
  * Synchlonizedされたリスト
  */
 List<String> dataList;

 /**
  * Synchlonizedされたリスト
  */
 List<String> errLogList;

 /**
  * apiのURL
  */
 String apiUrl = DEFAULT_API_URL;

 /**
  * ストリームを読み続けるためのスレッド
  */
 private Thread streamReadThread;
 
 public TwitterStreamReader(String userName, String password) {
  super();
  this.userName = userName;
  this.password = password;

  dataList = Collections.synchronizedList(new ArrayList<String>());
  errLogList = Collections.synchronizedList(new ArrayList<String>());
  
 }

 /**
  * 読み込みを開始する
  */
 public void start(){
  StreamReader streamReader = new StreamReader();
  
  streamReadThread = new Thread(streamReader);
  streamReadThread.start();
 }

 /**
  * 取得を停止する
*/
 public void stop() {
  this.isForceStop = true;
 }
 
 /**
  * データ取得中かどうかを返す
  * @return
  */
 public boolean isRunning(){
  return streamReadThread.isAlive();
 }
 
 /**
  * 取得済みのTweetデータのリストを取得する
* これまでに読み込んだデータは削除される
  * @return 是までに読み込んだデータ
  */
 public List<String> readStoredList(){
  List<String> storedList;
  synchronized (dataList) {
   storedList = new ArrayList<String>(dataList);
   dataList.clear();
  }

  return storedList;
 }
 
 /**
  * エラーログのリストを取得する
* これまでに読み込んだデータは削除される
  * @return 是までに読み込んだデータ
  */
 public List<String> readErrLogList(){
  List<String> storedList;
  synchronized (errLogList) {
   storedList = new ArrayList<String>(errLogList);
   errLogList.clear();
  }
  return storedList;
 }

 /**
  * 強制停止信号を送ったかどうか
  * @return the isForceStop
  */
 public boolean isForceStop() {
  return isForceStop;
 }
 
 /**
  * データ読み込み用クラス
  * @author tori
  *
  */
 class StreamReader implements Runnable{
  @Override
  public void run() {
   isForceStop = false;
   while(!isForceStop){
    InputStreamReader isr = null;
    BufferedReader br = null;
    try{
     URL connectUrl = new URL(apiUrl);
     HttpURLConnection con = (HttpURLConnection)connectUrl.openConnection();
     
     con.setRequestMethod("GET");
     con.setDoOutput(true);
     con.setInstanceFollowRedirects(true); 

     Authenticator auth = new Authenticator(){
      public PasswordAuthentication getPasswordAuthentication(){
       return new PasswordAuthentication(userName, password.toCharArray());
      }
     };
     Authenticator.setDefault(auth);
     

     isr = new InputStreamReader(con.getInputStream(), "UTF8");
     br = new BufferedReader(isr);
     while(!isForceStop){
      String tweet = br.readLine();
      synchronized (dataList) {
       dataList.add(tweet);
      }
     }
    }catch(Exception e){
     StringBuffer buf = new StringBuffer();
     buf.append(e.getClass().getName()+"\n");
     for(StackTraceElement ste:e.getStackTrace()){
      buf.append(String.format("\tat %s.%s(%s:%d)\n", ste.getClassName(), ste.getMethodName(), ste.getFileName(), ste.getLineNumber()));
     }
     synchronized (errLogList) {
      errLogList.add(buf.toString());
     }
    }finally{
     try{
      br.close();
     }catch(Exception e){
     }
     try{
      isr.close();
     }catch(Exception e){
     }
    }
   }
  }
 }
}

2011年7月30日土曜日

じゃんけん大会の必勝法

世の中こんなブログであふれている.
たった5万円から億万長者になった、成功の9ステップ

非常に学びが多く、ここに書かれたことを実践することで、自分なりの成功に近づけると思った。

とか書いてあるけれど,
成功例だけ見てその結果を模倣しても,
それは単にじゃんけん大会で勝った人の話を聞いているだけじゃないかと思う.
何万人でじゃんけん大会をしても,必ず一人は優勝者が出る.
ただ,その優勝者は偶然優勝しただけであって,必勝法など無い.
にもかかわらず,その人がどう優勝したかを聞いて,それを実践してじゃんけん大会で優勝しようとしているようなもの.

ある行動が成功に結びつくかどうかを知りたいのならば,
その行動を行った人を一定量サンプリングして,その中の成功例と失敗例を調べるべき.
成功した人のほんとどがやっていた行動をすれば成功する信じるのならば,みんな毎日息をしていればいいと思う.
成功者はみんな息をしているんだから.

というわけで,そんな簡単な統計学も分からないようではやっぱり成功しないんじゃないだろうか.

2011年7月13日水曜日

作業用にSugerSync

出張が多い身としては,職場のPCとノートPCとでデータを共有したいんだけど,
いちいち動かすのが面倒くさい.
そんなときは,ファイル共有アプリである,DropBoxがスタンダードでしょう.
DropBoxフォルダに入っているデータを自動的に全PCで共有してくれるので,面倒なことを考えなくてもフォルダにファイルをぶちこんでおけば入れ忘れに悩む必要は無い.
とはいえ,特定のフォルダ以下にデータを入れておかないと共有されないのがちょっと不便.
ドキュメントならそれでもいいけど,Eclipseを使ってプログラミングしているものを共有しようとすると,最初からDropbox内にプロジェクトを作らなければいけないし,共有をやめようと思ったら一々フォルダの場所を動かして設定も変更しないといけないのが欠点.

んで,色々探したらSugarSyncというのがあるらしい.
こっちはDropBoxと違って任意のフォルダを共有可能.
共有したいフォルダは一個一個選ばなければいけないけど,一度指定すればその下に作ったフォルダは全部教諭されるので,作業中のフォルダだけ共有するのも楽勝.
フォルダ内の共有したくないデータは除外出来るので,プログラムプロジェクトのなかで,ログフォルダだけ除外とかも余裕.
容量は5~5.5G.これは,Dropboxと同じ.
ただ,作業の必要なくなったら共有をやめればいいだけなので,Dropboxより使い勝手が良いかも.
お金さえ払えば250Gまでいけるらしいけど,そこまでは必要ない気がする.
iPodとかiPadとかアンドロイド携帯でも使えるらしいけど,そっちは試したことが無いのでよく分からない.誰か試したら教えて.
Dropboxを併用できるのもポイント高い.
両方使えば最初から11G使えるようにもなるので,半永久共有したいファイルはDropBoxに,一時的なファイルはSugerSyncに入れると容量を節約しつつ使えてよい.
というわけで,外用のノートPCと職場のPCを併用している人にはお勧め.
家と職場でも使えるけど.

SugarSyncを容量5.5Gで開始
SugarSyncを容量5Gで開始

Dropboxを容量5.5Gで開始
Dropboxを容量5Gで開始

2011年6月11日土曜日

震災時のTweetデータの分析

先日共同研究者を募集したTweetデータについて,簡単な分析を行ってみました.

まず,総Tweet数ですが,3月5日から3月24日までで3億3235万8199Tweetでした.
日ごとのTweet数の内訳は,図1の通りです.
図1 Tweet数の変位
ただし,震災直後(3月12~15日)あたりは計画停電などの影響で十分にデータが取れていない可能性もあります.後々再収集を試みましたが,すべて収集出来ているとは限りません.

まあ,とはいえ3月11日にTweet数が一気に増加したのは間違いなさそうです.

次に,震災時にどの県が注目されていたかを分析しました.
各県名がTweetされた回数について,日常の1時間あたりの平均を県名Tweet数を1としたときに,震災時に何倍Tweetされたかを日本地図上に色分けして乗せました.
色が濃いほど日常よりも多くつぶやかれていることを示します.
autoボタンを押せば,時系列で見ることが出来ます.
画面がチラ付くのはご愛敬.

やはり,地震直後は「宮城」「福島」などがTweetされていますが,
時間とともに「宮城」などは減少し,「福島」が目立つことが分かります.
二日目付近からは,原発に注目が行っていたのでしょう.
また,長野や静岡でも地震が発生すると,大きく注目されていることが分かります.

ここから分かることはまだまだ少ないですが,今後さらに多くの情報をデータから抽出して,
震災時に何が起きたのかを明らかにしていきたいと思います.

2011年6月8日水曜日

ポモドーロテクニック

研究生活を続けていると,集中して論文を書いたりする作業が必要になったりします.
でも,つい他のことが気になって論文書きながら別の事をやってしまったりとかありますよね.
そんなときに集中力を維持するのに有効なテクニックとして,ポモドーロテクニックがあります.

これは,25分間は集中して一つの作業をして,その後5分間休憩し,
また25分作業する,というのを続けるテクニックです.
作業中の25間はメールが来てもFacebookに書き込みがあっても,全部無視して作業に集中します.
Twitterへの書き込みだって控えます.
電話は出ないとダメかもしれないけど.
雑用は5分ですませて,ついでに少し休みます.
それを4~5回繰り返すと作業効率がぐっとアップするというわけです.

本当かよ~とか思いつつタイマーを用意してやってみたのですが,
これが意外といい.
確かに,集中出来るので思ったより作業が進む.
特に,レポートの採点とか論文の査読とかあんまり楽しくない作業にはぴったり.

というわけで,単にタイマーを使うのではなく,
ちゃんと25分を計ってくれるアプリがいいなあと思って作成しました.
ポモドーロタイマー
作業回数と内容を入力してスタートするだけで25分間+5分の休憩を淡々と記録していってくれます.

しかも,Twitterと連携して作業開始時にTwitter上に宣言をしてくれます.
今作業中だよ,と.
つまり,作業をサボってTwitterで遊んでいると他の人にばれてしまうわけですね.

というわけで,集中力のないそこのあなた.
是非使ってみてください.

外部関連記事:
ポモドーロテクニックについて

2011年4月7日木曜日

東日本大震災時のTwitterデータを用いた共同研究者募集

東日本大震災が発生してから一ヶ月が経過しようとしています.

そんななか,
Twitter検索の@PENGUINANA_さんのご協力の下,
2011年3月5日から24日までのTwitterでつぶやかれた日本語のTweetのうち2億6688万9069Tweetを入手しました.

含まれているデータには,
・TweetID(1ツイート毎に割り当てられる唯一のID)
・ScreenName(ツイート当時の物)
・Contents(本文)
・Source(ツイート元)
・Time(ツイート時間)
・reply_to(Reply機能を使ったときのリプライ先TweetID)
・reply_to_sc(Replyを受けた人のScreenName)
があります.

2011/4/8追記
各Tweetに含まれるハッシュタグと,はてなキーワードを抽出したメタデータもあります.
また,@User関連のデータも作成予定です.
追記ここまで.

近いうちに公開したいと思いますが,
その前に共同で研究してくださる方を募集します.

ネタとしては,
・情報の信頼性分析
・情報伝播の分析
を考えていますが,これにこだわりません.

一緒に研究しようぜ!という方はメール(ご存じの方)か,Twitter(@toritorix)につぶやくか,このエントリーのコメントでご連絡ください.

あ,ちなみに本件に関して(今のところ)予算はありませんw

2011年3月7日月曜日

数の暴力

Googleがインフルエンザの流行を予測する
http://www.google.org/flutrends/intl/ja/about/how.html
大量のデータがあるというのはそれだけですごいことができるということ.
なんというか,Googleの中の人がうらやましい.
そして,なんとかこういうデータを手に入れることが出来ないものかと悶々としてしまいます.

そのほかの記事.
http://www.kk.org/thetechnium/archives/2008/06/the_google_way.php
http://www.wired.com/science/discoveries/magazine/16-07/pb_theory/