[ヅラド] JavaとTwitter4JでTwitterのツイート検索結果をHTML出力する の焼き直し。
ちがうのは、『検索結果』ではなく『指定したユーザー』のツイートを出力するところ。
ついったー(Twitter)発言まとめツール がすばらしかったので、HTML構造や CSS の id や class はこれを踏襲している。
動作確認環境
* Windows XP SP3
* JDK 1.6
* Twitter4J version 2.1.1
ソースコード
import java.io.*;
import java.text.*;
import java.util.*;
import twitter4j.*;
public class UserTimelinePrinter {
public static void main(String[] args) throws Exception {
String user = "nilab"; %lt;- ここに取得したいユーザー名を指定
Integer limit = 1000;
String outfile = "outfile.html";
PrintStream out = new PrintStream(new File(outfile), "UTF-8");
// PrintStream out = System.out;
print(user, limit, out);
}
private static String KAIGYO = "\r\n";
/**
* 検索クエリにマッチしたツイートを出力します。
* @param searchQuery 検索クエリ
* @param limit 出力するツイートの最大数
* @param out 出力先
* @throws 何かエラー
*/
private static void print(String user, Integer limit, PrintStream out) throws Exception {
// APIからツイートを取得
List<Status> tweets = getTweets(user, limit);
// APIで取得すると新しいほうから古いほうへの並びになっているので、ツイートが古い順になるようソート。
Collections.reverse(tweets);
// ツイートを出力
print(tweets, limit, out);
}
/**
* 検索クエリにマッチしたツイートを返します。
* @param searchQuery 検索クエリ
* @param limit 取得する最大数
* @return 検索クエリにマッチしたツイート
* @throws 何かエラー
*/
private static List<Status> getTweets(String user, Integer limit) throws Exception {
List<Status> tweets = new ArrayList<Status>();
try{
// APIにてツイートを取得
TwitterFactory factory = new TwitterFactory();
Twitter twitter = factory.getInstance();
final int count = 200;
Paging paging = new Paging(1, count);
long max_id = 0;
while(true){
// ツイートを取得
ResponseList<Status> statusList =
twitter.getUserTimeline(user, paging);
System.out.print("*"); // APIを1回コールしたという表示
// ツイートが取得できなくなったら終了
if(statusList.size() == 0){
break;
}
tweets.addAll(statusList);
// ツイートが欲しい最大数以上になったら終了
if(limit != null && limit <= tweets.size()){
break;
}
// 次にAPIをたたくときは、いま取得したツイートより昔のを取得するように
max_id = statusList.get(statusList.size() - 1).getId() - 1;
paging.setMaxId(max_id);
// 負荷高いと怒られるかもしれないから
try{Thread.sleep(1000);}catch(Exception e){}
}
System.out.println("");
}catch(Exception e){
// エラーが発生してもスタックトレースを出力するだけで
// ここまでに取得したツイートは返すことにする
e.printStackTrace();
}
return tweets;
}
/**
* ツイートを出力します。
* @param tweets 出力するツイートの最大数
* @param out 出力先
*/
private static void print(List<Status> tweets, Integer limit, PrintStream out){
out.print("<table class=\"twitter_matome\">");
out.print(KAIGYO);
int num = limit != null ? Math.min(limit, tweets.size()) : tweets.size();
for(int i=0; i<num; i++){
Status tweet = tweets.get(i);
out.print(toString(tweet));
}
out.print("</table>");
out.print(KAIGYO);
}
/**
* 出力するツイートを文字列化します。
* @param t 出力するツイート
* @return 文字列化されたツイート
*/
private static String toString(Status t){
StringBuffer buf = new StringBuffer();
buf.append("<tr class=\"twitter_matome_status\" id=\"" + t.getId() + "\">");
buf.append(KAIGYO);
buf.append("<td class=\"twitter_matome_image\">");
buf.append("<a href=\"http://twitter.com/" + escapeHtml(t.getUser().getScreenName()) + "\">");
// プロフィールアイコンにTwitter標準のURLを使うときはこっち↓
buf.append("<img src=\"" + escapeHtml(t.getUser().getProfileImageURL().toString()) + "\" width=\"48\" />");
// プロフィールアイコンに http://tweetimag.es/ を使うときはこっち↓
//buf.append("<img src=\"http://img.tweetimag.es/i/" + escapeHtml(t.getUser().getScreenName()) + "_n\" width=\"48\" />");
buf.append("</a>");
buf.append("</td>");
buf.append(KAIGYO);
buf.append("<td class=\"twitter_matome_name\">");
buf.append("<a href=\"http://twitter.com/" + escapeHtml(t.getUser().getScreenName()) + "\">");
buf.append(escapeHtml(t.getUser().getScreenName()));
buf.append("</a>");
buf.append("</td>");
buf.append(KAIGYO);
buf.append("<td class=\"twitter_matome_text\">");
buf.append(normalizeText(t.getText()));
buf.append("</td>");
buf.append(KAIGYO);
buf.append("<td class=\"twitter_matome_date\">");
buf.append("<a href=\"http://twitter.com/" + escapeHtml(t.getUser().getScreenName()) + "/statuses/" + t.getId() + "\">");
buf.append(normalizeDate(t.getCreatedAt()));
buf.append("</a>");
buf.append("</td>");
buf.append(KAIGYO);
buf.append("</tr>");
buf.append(KAIGYO);
return buf.toString();
}
private static DateFormat createDateFormat(){
// 日本人ですからJST、そしてLocaleはJAPANで。
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.JAPAN);
df.setTimeZone(TimeZone.getTimeZone("JST"));
return df;
}
public static final DateFormat yyyyMMddHHmmss = createDateFormat();
/**
* 出力するツイートの日時情報を文字列化します。
* @param d 日時情報
* @return 文字列化された日時情報
*/
private static String normalizeDate(Date d){
return yyyyMMddHHmmss.format(d);
}
/**
* HTML用えすけーぷ。
* @param s 文字列
* @return 適切に変換された文字列
*/
private static String escapeHtml(String s){
return
s.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("'", "'")
.replace("\"", """);
}
/**
* 出力するツイート内容を適切な文字列に変換します。
* @param s ツイート内容
* @return 適切に変換された文字列
*/
private static String normalizeText(String s){
s = escapeHtml(s);
// ツイートに改行が含まれることがあるので何とかする
s = s.replaceAll("\r\n", "\n");
s = s.replaceAll("\r", "\n");
s = s.replaceAll("\n", "<br />");
return s;
}
}
出力結果の例
nilab | あいたくて あいたくて ふるえる | 2010-07-09 16:02:08 | |
nilab | 姫家具の話。このまえTVでも白馬の王子様とお姫様なりたい妄想と家具の話してた。 | 2010-07-09 16:09:30 | |
nilab | list of foursquare badges « presence: a journal by tony felice http://tonyfelice.wordpress.com/foursquare/ | 2010-07-09 17:25:29 | |
nilab | foursquareでワールドカップの試合中に”Go+国名”とshoutすると『Bing Home Turf』バッジがもらえる? http://www.nilab.info/zurazure2/001129.html | 2010-07-09 20:51:47 | |
nilab | Twitter Search は最近のツイートしか検索できないからつらいな。。。 | 2010-07-09 21:41:39 |
出力結果の例(HTMLの中身)
<table class="twitter_matome">
<tr class="twitter_matome_status" id="18099257860">
<td class="twitter_matome_image"><a href="http://twitter.com/nilab"><img src="http://a1.twimg.com/profile_images/25307672/zlashdot_profile_normal.jpg" width="48" /></a></td>
<td class="twitter_matome_name"><a href="http://twitter.com/nilab">nilab</a></td>
<td class="twitter_matome_text">あいたくて あいたくて ふるえる</td>
<td class="twitter_matome_date"><a href="http://twitter.com/nilab/statuses/18099257860">2010-07-09 16:02:08</a></td>
</tr>
<tr class="twitter_matome_status" id="18099592025">
<td class="twitter_matome_image"><a href="http://twitter.com/nilab"><img src="http://a1.twimg.com/profile_images/25307672/zlashdot_profile_normal.jpg" width="48" /></a></td>
<td class="twitter_matome_name"><a href="http://twitter.com/nilab">nilab</a></td>
<td class="twitter_matome_text">姫家具の話。このまえTVでも白馬の王子様とお姫様なりたい妄想と家具の話してた。</td>
<td class="twitter_matome_date"><a href="http://twitter.com/nilab/statuses/18099592025">2010-07-09 16:09:30</a></td>
</tr>
<tr class="twitter_matome_status" id="18102844267">
<td class="twitter_matome_image"><a href="http://twitter.com/nilab"><img src="http://a1.twimg.com/profile_images/25307672/zlashdot_profile_normal.jpg" width="48" /></a></td>
<td class="twitter_matome_name"><a href="http://twitter.com/nilab">nilab</a></td>
<td class="twitter_matome_text">list of foursquare badges « presence: a journal by tony felice http://tonyfelice.wordpress.com/foursquare/</td>
<td class="twitter_matome_date"><a href="http://twitter.com/nilab/statuses/18102844267">2010-07-09 17:25:29</a></td>
</tr>
<tr class="twitter_matome_status" id="18111904801">
<td class="twitter_matome_image"><a href="http://twitter.com/nilab"><img src="http://a1.twimg.com/profile_images/25307672/zlashdot_profile_normal.jpg" width="48" /></a></td>
<td class="twitter_matome_name"><a href="http://twitter.com/nilab">nilab</a></td>
<td class="twitter_matome_text">foursquareでワールドカップの試合中に”Go+国名”とshoutすると『Bing Home Turf』バッジがもらえる? http://www.nilab.info/zurazure2/001129.html</td>
<td class="twitter_matome_date"><a href="http://twitter.com/nilab/statuses/18111904801">2010-07-09 20:51:47</a></td>
</tr>
<tr class="twitter_matome_status" id="18114751452">
<td class="twitter_matome_image"><a href="http://twitter.com/nilab"><img src="http://a1.twimg.com/profile_images/25307672/zlashdot_profile_normal.jpg" width="48" /></a></td>
<td class="twitter_matome_name"><a href="http://twitter.com/nilab">nilab</a></td>
<td class="twitter_matome_text">Twitter Search は最近のツイートしか検索できないからつらいな。。。</td>
<td class="twitter_matome_date"><a href="http://twitter.com/nilab/statuses/18114751452">2010-07-09 21:41:39</a></td>
</tr>
</table>
# いまさらだけど、もしかしてTwitterユーザーがアイコンをアップロードしなおしたら画像参照できなくなるんじゃ・・・
参考
tags: zlashdot Java Java Twitter Twitter4J
Posted by NI-Lab. (@nilab)