2011年11月17日木曜日

#サンタクラウドの集計(その2)

スズキです。

下記に引き続き、少しづつ進めています。
#サンタクラウドの集計(その1)

該当Tweetの取得は検索APIを利用しているのですが、時間が経つと
昔のTweetが検索できなくなってしまう可能性があります。

なので前回(#AWS77)は、Tweetデータを"togetter"から取得(スクレイピング)を
していたのですが、スクレイピングは好きじゃないので、今回は前回のTweetデータに
新規Tweetを追加する形にしました。

具体的には検索からのTweetの集合から前回のTweet集合の差分をとり、
その差分を前回のTweet集合に追加したものを、最新のTweet集合としています。
そして、その処理を一時間に一回実行しています。

最終的なスクリプトは下記のような感じになっています。

// 初期設定
require_once("/opt/aws/php/default/sdk.class.php");
date_default_timezone_set("Asia/Tokyo");
define("AWS_KEY"       , "AAAAAAAAAAAAAAAAAAAA");
define("AWS_SECRET_KEY", "ssssssssssssssssssssssssssssssssssssssss");
$s3 = new AmazonS3();
$s3->set_region(AmazonS3::REGION_APAC_NE1);

// 前回作成したランキング情報の取得
$response = $s3->get_object(
    "www.suz-lab.com",
    "santacloud/tweet.json",
    array("curlopts" => array(CURLOPT_SSL_VERIFYPEER => false))
);
$ranking_old = json_decode($response->body, true);

// 最新のランキング情報の取得
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$keyword = "%23jawsug%20%23%E3%82%B5%E3%83%B3%E3%82%BF%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89"; 
$page    = 1;
$ranking_current = array();
do {
    curl_setopt($curl, CURLOPT_URL, "http://search.twitter.com/search.json?result_type=recent&rpp=100&page=$page&q=$keyword");
    $tweet_json   = curl_exec($curl);
    $tweet_object = json_decode($tweet_json, true);
    foreach($tweet_object["results"] as $tweet) {
        if(strpos($tweet["text"], "RT ") === false) {
            array_push($ranking_current, array(
                "tweet_id"         => $tweet["id_str"],
                "tweet_text"       => $tweet["text"],
                "tweet_user_name"  => $tweet["from_user"],
                "tweet_user_image" => $tweet["profile_image_url"],
            ));
        }
    }
    $page++;
} while(count($tweet_object["results"]));

// 前回のランキング情報と最新のランキング情報の差を取得し、その差を前回のランキングに追加
$ranking_diff = array_udiff($ranking_current, $ranking_old, function($a, $b) {
    if($a["tweet_id"] === $b["tweet_id"]) {
        return 0;
    } else {
        return ($a["tweet_id"] > $b["tweet_id"]) ? 1 : -1;
    }
});
$ranking_tmp = array_merge($ranking_diff, $ranking_old);

// Retweet情報を取得
$ranking = array();
foreach($ranking_tmp as $tweet) {
    curl_setopt($curl, CURLOPT_URL, "http://api.twitter.com/1/statuses/" . $tweet["tweet_id"] . "/retweeted_by.json");
    $retweet_json   = curl_exec($curl);
    $retweet_object = json_decode($retweet_json, true);
    if(!isset($retweet_object["error"])) {
        $tweet["retweet_users"] = array();
        foreach($retweet_object as $retweet) {
            array_push($tweet["retweet_users"], array(
                "retweet_user_name"  => $retweet["screen_name"],
                "retweet_user_image" => $retweet["profile_image_url"]
            ));
        }
        array_push($ranking, $tweet);
    }
}

// Retweet数順にソート
usort($ranking, function($a, $b) {
    if(count($a["retweet_users"]) == count($b["retweet_users"])) {
        return 0;
    } else {
        return (count($a["retweet_users"]) > count($b["retweet_users"])) ? -1 : 1;
    }
});

// 最新のランキング情報をS3にアップロード
$response = $s3->create_object("www.suz-lab.com", "santacloud/tweet.json", array(
    "body"        => json_encode($ranking),
    "acl"         => AmazonS3::ACL_PUBLIC,
    "contentType" => "text/javascript",
    "curlopts"    => array(CURLOPT_SSL_VERIFYPEER => false)
));

// 最新のランキング情報をアーカイブとしてS3にアップロード
$date = date("YmdHis");
$response = $s3->create_object("www.suz-lab.com", "santacloud/tweet/$date.json", array(
    "body"        => json_encode($ranking),
    "acl"         => AmazonS3::ACL_PUBLIC,
    "contentType" => "text/javascript",
    "curlopts"    => array(CURLOPT_SSL_VERIFYPEER => false)
));

次は下記を改善する予定です。
  • 同じようなTweetをマージ
  • TwitterAPIの100回/時の実行制限対策

今のTweetは80弱なので、そとそろ100回/時の対策をしないと...
--------
http://www.suz-lab.com

0 コメント: