2010年4月28日水曜日

Twitter ストリーミングAPIをgardenhoseで使う

とりあえず,TwitterストリーミングAPIでデータをもっと欲しいので,
gardenhoseに申し込んでみた.
http://twitter.com/help/request_streaming
にアクセスして,名前,所属,E-Mail,URL,申請理由を書くだけ.

登録したら速攻使えるようになりました.
というか,sampleの性能があがって,gardenhoseになりました.
申請理由とか真面目に書いたのに,あんまり意味がない.

で,どのくらいとれるようになったかを確認.
sampleではIDの下一桁が0-4のTweetがとれていたけど,gardenhoseだと下2桁が0-14のTweetが取得出来ていた.およそ3倍の性能と言ったところ.
それでも,全体の15%しかとれない.これが多いか少ないかは難しいところだ.

sampleでは日本語のTweetが秒間6.5個くらいとれたのに対して,
gardenhoseでは日本語のTweetが秒間20個くらいとれた.
ちなみに,計測時間は19:30くらい.
昼間は秒間10Tweetくらいだった.だいぶ差があるなあ.

2010年4月27日火曜日

日本語が含まれるかどうかの判定

TwitterのストリーミングAPIから日本語が使われているTweetだけ取得したいので,
日本語マッチングをやってみた.
Matcher m = Pattern.compile("([\\p{InHiragana}\\p{InKatakana}])").matcher(text);
boolean isJapanese = m.find();
\p{InCJKUnifiedIdeographs}で漢字もとれるけど,漢字オンリーのつぶやきは中国系の人の物が多いみたいなので,ひらがなかカタカナが含まれるもののみにした.

2010年4月26日月曜日

Twitter Streaming APIをJavaで試してみる


2011年10月05日追記:
Streaming APIがHTTPS対応となったので,若干変更が必要です.
詳しくは,こちらのバージョンをご覧ください.

2010年12月24日追記:
Twitter4jを使ったバージョンを作ったので,そちらを使った方が良いと思われます.


TwitterのStreamingAPIにがぜん興味が出てきたので,Javaで実装してみた.
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 = "http://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();
 }

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

  return storedList;
 }
 
 /**
  * エラーログのリストを取得する<br>
  * これまでに読み込んだデータは削除される
  * @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){
     }
    }
   }
  }
 }
}


参考にしたのは,
この辺.

どんどん取ってくるためにThread化したけど,使いたい人は好きに作り直せばいいと思う.

2010年4月25日日曜日

App Engine覚書

Localhostで接続したときのDataScoreViewなど。
http://localhost:8888/_ah/admin

忘れっぽいエンジニアのJakarta Strutsリファレンス
http://struts.wasureppoi.com/

The class "com.appspot.****.className" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found.
org.datanucleus.exceptions.ClassNotPersistableException: The class "com.appspot.****.className" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found.
ってな謎のエラーが発生してJSPをうまく処理できないとき。
http://d.hatena.ne.jp/y_koh/20090531/1243766131

とりあえず、datanucleus-appengine-1.0.4.1.final.jarをビルドパスからはずせばいいみたい。

2010年4月23日金曜日

社会実情データ

いろんな社会調査のデータが乗っている.
http://www2.ttcn.ne.jp/honkawa/
便利そう.

2010年4月9日金曜日

またか・・・

今年は研究室で3つも科研費出したのに,一つも通らなかった.
どんだけお金持ってくるのが苦手な研究室なんだ・・・
メインのテーマなんて5年くらい連続で落ち続けてるし.
どうすりゃいいんだ,これ.

分担で一つ通ってるだけマシと思うしかないか.

2010年4月2日金曜日

SNS関連論文サーベイ

SNS関連の論文をサーベイしてみよう.
とりあえず,列挙する.
足りないもの,読んだ方がいい物があったら是非コメント欄で教えてください.