【Twitter4J】Streaming APIのsampleで各ツイートのlang(言語情報)を取得する方法


Twitter4JでStreaming APIのsampleで各ツイートのlang(言語情報)を取得する方法についてです。
現時点での最新バージョンではメソッドがまだ実装されていないようなので、ツイート情報(status)からJackson Java JSON-processorを使用して取得します。

あらまし

この言語判定はまず3月6日(March 6, 2013)にREST APIで実装され、次いで3月26日(March 26, 2013)にStreaming APIに実装されました。
機能の詳細については次の公式ブログに掲載されていました(現在はリンク切れ)
 →Introducing new metadata for Tweets | Twitter Developers
(この公式ブログでは言語判定に加えて、filter_levelも紹介されています。)
 

<該当箇所>
The new lang attribute specifies the language the Tweet was written in, as identified by Twitter's machine language detection algorithms. The values will be valid BCP 47 language identifiers, and may represent any of the languages listed on Twitter's advanced search page, or "und" if no language could be detected. This field enables consumers of Tweet data, such as analytics services or real-time search streams, to offer language-specific curation, aggregation and analysis of Tweet content.

コード例

さて、方法は次のようになります。(status_getLangの部分です)

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;


//JSONの取得・分解にはJackson Java JSON-processorを使用
//ダウンロードなどは下記ページ
//http://jackson.codehaus.org/
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

import twitter4j.*;
import twitter4j.json.DataObjectFactory;


//Streaming APIのsampleでstatusのlang(言語情報)を取得する
public class status_getLang_sample {

    public static void main(String[] args){

        try{

            //自動的に認証してくれる
            //(バージョン2.2.4以降はgetInstance()ではなくgetSingleton()を推奨)
            new TwitterStreamFactory();
            TwitterStream twitterstream = TwitterStreamFactory.getSingleton();

            twitterstream.addListener(new MyStatusAdapter());
            twitterstream.sample();

        } catch(Exception e){
            e.printStackTrace();
        }
    }
}

//出力する
class MyStatusAdapter extends StatusAdapter {

    public void onStatus(Status status){

        BufferedWriter wr = null;

        //書き出し先のファイルを指定
        String fileName = "○○.txt";
        String outdata;


        try {

            //ユーザの情報を取得
            User user = status.getUser();

            //statusオブジェクトのJSON文字列を取得
            String rawJSON = DataObjectFactory.getRawJSON(status);

            //JSON文字列を分解し必要な情報を取得
            //(statusオブジェクトのlang)
            String status_getLang = null;

            try {
                status_getLang = parseJSON(rawJSON);

            } catch (JsonParseException e) {
                e.printStackTrace();
            }

            //utf-8を指定、追記可能
            wr = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName,true), "utf-8"));

            //ツイートから改行記号を除去(半角スペースに変換)
            String strText = status.getText();
            strText = strText.replaceAll("\r\n"," ");
            strText = strText.replaceAll("\r"," ");
            strText = strText.replaceAll("\n"," ");

            //ツイートからタブ記号を除去(半角スペースに変換)
            strText = strText.replaceAll("\t"," ");


            //書き出し(ツイートの言語設定、ユーザの言語設定、タイムゾーン、位置情報、日時、利用アプリ、ユーザ名、ツイート)
            outdata = status_getLang + "\t" + user.getLang() + "\t"
                    + user.getTimeZone() + "\t" + status.getGeoLocation() + "\t" + status.getCreatedAt() + "\t"
                    + status.getSource() + "\t" +user.getScreenName() + "\t" + strText;

            wr.write(outdata);
            wr.write("\n");

            wr.flush();
            wr.close();

        }catch (IOException e) {
            e.printStackTrace();
        }
    }


    //JSON文字列からオブジェクトに変換する
    private static String parseJSON(String str) throws JsonParseException, IOException {

        JsonFactory factory = new JsonFactory();
        JsonParser jp = factory.createJsonParser(str);

        if(jp.nextToken() == JsonToken.START_OBJECT) {
            while (jp.nextToken() != JsonToken.END_OBJECT) {
                String _name = jp.getCurrentName();
                jp.nextToken();


                if(_name.equals("user")) {
                    jp.skipChildren();
                } else {

                    //言語設定ならば返す
                    if(_name == "lang") {
                        return jp.getText();
                    }
                }
            }
        } else {
            jp.skipChildren();
        }
        return null;
    }
}

言語判定の精度

この言語判定の精度を検証したところ、非常に高い精度であることが分かりました。
別記事としましたのでご覧ください。
 →ツイートの言語判定の精度が高すぎる!日本語はなんと100%!完璧!