APIのデータ解析
PixivだとiPhone用のAPIでランキングや検索結果がデータとして取得できるわけだが、これがめんどくさい。
例としてデイリーランキング取るとすると、
http://iphone.pxv.jp/iphone/ranking.php?mode=day
を叩くが、その結果がこちら。
"16774382","426002","jpg","レミリアと咲夜","21","かる","http://img21.pixiv.net/img/amethyst21/mobile/16774382_128x128.jpg",,,"http://img21.pixiv.net/img/amethyst21/mobile/16774382_480mw.jpg",,,"2011-02-18 19:23:42","東方" "レミリア" "咲夜" "なにこれかっこいい" "ふつくしい" "なにこれすごい" "紅魔郷" "咲レミ" "東方Project1000users入り",,"3773","37378","85199",,,,,"2417","8","amethyst21",, ・・・
xmlとかjsonとかじゃなく、 " と , で区切られてる・・・
つーことでちょいと解析。
1作品は改行にて区切られており(キャプション中の区切りもあるため注意)さらにそれらは26個の詳細情報が含まれている。この区切りは , 。
詳細情報については頭から以下。
- 作品ID
- 作者ID(数字)
- 拡張子
- タイトル
- サーバ番号
- 作者名
- 128x128画像のURL
- ?
- ?
- 480mw画像のURL
- ?
- ?
- 投稿日時
- タグ
- 使用ソフト
- 評価回数
- 総合点
- 閲覧数
- キャプション
- ページ数
- ?
- ?
- ?*1
- ?*2
- 作者ID(ユーザー名)
- ?
?は不明。基本的に値が入っていないものがほとんどだが、*1*2は入ってる値が謎なもの。*1は見た感じ4桁くらいの数字だけどapi叩くごとに値が増えるから評価とかと関係があるかも。*2は2桁ってことくらいでよくわからん。
画像URLのあたりの不明なのは未実装のサイズの画像のURLを格納するんかなーと思ってみたり。つーかそもそも
http://imgサーバ番号(2桁).pixiv.net/img/作者ID(ユーザー名)/mobile/作品ID_画像サイズ.拡張子
が画像のURLになるからわざわざURL含めないでもいい気がするけどねー。ちなみにPC用画像にも直接アクセス可能。ログイン済みでクッキー必要だけど。
public ArrayList<HashMap<String, String>> getRankingItems(){ try { URL url = new URL( "http://iphone.pxv.jp/iphone/ranking.php?mode=day"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); BufferedReader br = new BufferedReader(new InputStreamReader( con.getInputStream(), "utf-8")); String line; StringBuffer str = new StringBuffer(); ArrayList<String> details = new ArrayList<String>(); while ((line = br.readLine()) != null) { str.append(line); } parse(details, str.toString().split(",", 2)); ArrayList<HashMap<String, String>> items = new ArrayList<HashMap<String, String>>(); for (int i = 0; i < details.size() / 26; i++) { HashMap<String, String> item = new HashMap<String, String>(); item.put("id", details.get(i*26)); item.put("authorid", details.get(i*26+1)); item.put("extension", details.get(i*26+2)); item.put("title", details.get(i*26+3)); item.put("server", details.get(i*26+4)); item.put("authorname", details.get(i*26+5)); item.put("128url", details.get(i*26+6)); item.put("?1", details.get(i*26+7)); item.put("?2", details.get(i*26+8)); item.put("480url", details.get(i*26+9)); item.put("?3", details.get(i*26+10)); item.put("?4", details.get(i*26+11)); item.put("time", details.get(i*26+12)); item.put("tag", details.get(i*26+13)); item.put("soft", details.get(i*26+14)); item.put("review", details.get(i*26+15)); item.put("score", details.get(i*26+16)); item.put("view", details.get(i*26+17)); item.put("caption", details.get(i*26+18)); item.put("page", details.get(i*26+19)); item.put("?5", details.get(i*26+20)); item.put("?6", details.get(i*26+21)); item.put("?7", details.get(i*26+22)); item.put("?8", details.get(i*26+23)); item.put("userid", details.get(i*26+24)); item.put("?9", details.get(i*26+25)); items.add(item); } return items; } catch (Exception e) { return null; } } public String parse(ArrayList<String> details, String[] strarr) { if (strarr.length != 2) { return null; } else if (strarr[0].isEmpty() || strarr[0].startsWith("\"") && strarr[0].endsWith("\"")) { details.add(strarr[0]); strarr = strarr[1].split(",", 2); return parse(details, strarr); } else if (strarr[1].isEmpty() || strarr[1].startsWith("\"") && strarr[1].endsWith("\"")) { return strarr[1]; } else { String[] strarr2 = strarr[1].split(",", 2); strarr[0] = strarr[0].concat(strarr2[0]); strarr[1] = strarr2[1]; return parse(details, strarr); } }
parse()にて , で区切った詳細情報をdetailsのリストに放り込んであとは26個ごとにitemsにマッピングして突っ込むだけ。キャプション中に区切り文字の , が含まれてるといけないから安易にsplit()は使えなかったけどもうちょい効率いいのあるかも。
とりあえずこれ使ってviewerの実装やってきましょか