スクレイピングでタイムラインを1日分とか拾う

APIを使っても過去にさかのぼってuser_timelineを拾ってこれないのでPHPで直接Webを読んで1日分とか前回ひろった最後のidまでとかいただきます。


うごかすと$value['description']に抜き出したデータのHTMLが入ります。
//ここでPOST のとこでメールに送るなりXML-RPCなりコロ
してください
ストーキングとか彼氏の監視に便利です



HTTP_Clientを使ってます
かなりファンキー(特に正規表現部分)なのですぐに使えんくなるかもなので、エラー処理のとこでメール通知とかしたらいいかも

ソース

require_once "HTTP/Client.php"; 

$account = "rytich"; //抜き出すアカウント
$max_page = 11; //最大何ページ分スクレイピングするか
$validDatetime = true; //時間を表示するか
$validReplies = false; //@で始まる書き込みを使うか
$last_id = 0; //ここで前回のlast_idをDBとかから拾う
$page = 1;
$last_time = strftime("%Y-%m-%dT%H:%M:%S+00:00 ", mktime() - 118800);
$client =& new HTTP_Client();
while ($page <= $max_page) {
    $params['page'] = $page;
    $client->get("http://twitter.com/" . $account, $params);
    $result = $client->currentResponse();
    //$url = urldecode($_POST['url']);
    $code = mb_convert_encoding($result['body'], "UTF-8","JIS,UTF-8,SJIS,EUC-JP");
    if ($page == 1) {
        preg_match('/<p class="entry-title entry-content">(.+)<\/p>\n.*\n.*\/statuses\/(\d+)".*<abbr class="published" title="(.+)">/', $code, $matches);
        if (!isset($matches[1]) || $matches[1] == "") {
            //ここでエラー処理
        } elseif ($matches[2] <= $last_id || $matches[3] <= $last_time) {
            $value['description'] = "<p>今日はつぶやかんかった...</p>";
        } elseif ($validReplies == true || !preg_match("/^@/", trim($matches[1]), $hoge)) {
            //$last_id = $matches[3]; // ここでlast_idをDBとかに保存
            if ($validDatetime == true) {
                $value['description'] = '<p>' . trim($matches[1]) . ' <small>' . $matches[3] . '</small><br />';
            } else {
                $value['description'] = '<p>' . trim($matches[1]) . '<br />';
            }
        }
    }
    preg_match_all('/<span class="entry-title entry-content">\n(.+)\n.*\n.*\n.*\n.*\n.*\/statuses\/(\d+)".*<abbr class="published" title="(.+)">/', $code, $matches);
    if (!isset($matches[1]) || count($matches[1]) < 1) {
        //ここでエラー処理
    }
    foreach ($matches[1] as $key => $val) {
        if ($matches[2][$key] <= $last_id || $matches[3][$key] <= $last_time) {
            $value['description'] .= '</p>';
            //ここでPOST
            exit;
        } elseif ($validReplies == true || !preg_match("/^@/", trim($val), $hoge)) {
            if ($validDatetime == true) {
                $value['description'] .= trim($val) . ' <small>' . $matches[3][$key] . '</small><br />';
            } else {
                $value['description'] .= trim($val) . '<br />';
            }
        }
    }
    $page++;
}
$value['description'] .= '</p>';
//ここでPOST

説明

一日1回cronでまわす場合はidは関係ないのでこのままで使えます
周期を変える場合は$last_timeのマイナスしてる秒数でなんとかなりそう
(今は時差分入れて24時間マイナス)
不定期に動かす場合はidをどこかに保存しとかんといかん


あとprotectedでtwitterしてる場合は

$client =& new HTTP_Client();

の部分を

$auth = array('user' => 'twitterのアカウント', 'pass' => 'twitterのパスワード');
$client =& new HTTP_Client($auth);

にして

$client->get("http://twitter.com/" . $account, $params);

$client->get("http://twitter.com/account/archive", $params);

に変えるといけるかもしれないしいけないかもしれない