PHP で Twitter Stream を受信する

| コメント(0) | トラックバック(0)

Twitter APIには、コマンドを投げたら、応答が一回帰ってくるだけのREST APIと、一度接続するとダラダラとデータが流れてくる Stream API があります。

REST API は専用ライブラリーがあって、そんなに考える必要はないんですが、Stream API は TCP ちうか、SSL セッションをつないでソケット読み出しをハンドルしてあげないといけない。

とまぁ、ここまでは紹介してあるページがあったりするわけですが、実際にこれを動かしてみたところ、たまにツィートを取りもらすのですよ。別のStream 対応 Twitterクライアントで Home を垂れ流しつつ、スクリプトの結果を流してみると、たまに欠損するわけです。

なので、変数ダンプだなんだして調べてみたところ、fgets() を使って変数に読み込むデータが途中で途切れてることが発覚しました。サーバは一塊のデータとしてデータを送ってるんですが、TCPストリームにはデータの区切りという概念がないので、受信側で勝手にデータを途切れさせて、fgets() が中途半端な位置で返ってしまうんですね。これは C で recv() した時にも起こります。

ちうわけで、読み込んだデータが、途中で途切れてないかを調べて、途切れてたらつなぎ合わせるという処理が必要になります。あと、なんでか分からんのですが、一個のツィートデータが途切れてしまと、続きのデータが来る前に「あと何バイト残ってるよ」という数字だけが書かれた情報が送られてくる。これは読み飛ばさないと、データとして壊れちゃうんですね。

そんなわけで、つなぎ合わせ処理を入れたスクリプトはこんな感じ

require_once('config.php');
$url = 'https://userstream.twitter.com/1.1/user.json';
#$url = 'https://userstream.twitter.com/1.1/statuses/firehose.json';
$method = 'GET';

$oauth_parameters = array(
    'oauth_consumer_key' => CONSUMER_KEY ,
    'oauth_nonce' => microtime(),
    'oauth_signature_method' => 'HMAC-SHA1',
    'oauth_timestamp' => time(),
    'oauth_token' => ACCESS_TOKEN ,
    'oauth_version' => '1.0',
);

$a = $oauth_parameters;
ksort($a);
$base_string = implode('&', array(
    rawurlencode($method),
    rawurlencode($url),
    rawurlencode(http_build_query($a, '', '&', PHP_QUERY_RFC3986))
));
$key = implode('&', array(rawurlencode(CONSUMER_SECRET) , rawurlencode(ACCESS_TOKEN_SECRET)));
$oauth_parameters['oauth_signature'] = base64_encode(hash_hmac('sha1', $base_string, $key, true));

$fp = fsockopen("ssl://userstream.twitter.com", 443);
if ($fp) {
  fwrite($fp, "GET " . $url . " HTTP/1.1\r\n"
         . "Host: userstream.twitter.com\r\n"
         . 'Authorization: OAuth ' . http_build_query($oauth_parameters, '', ',', PHP_QUERY_RFC3986) . "\r\n"
         . "\r\n");
  while (!feof($fp)) {
    $read = fgets($fp);
    if(strlen($read) > 5)
    {
      if(preg_match('/^\{/' , $read))
        $line = $read;
      else
        $line .= $read;
    }
    $line = preg_replace('/[\s\n]+$/' , '' , $line);
    if(preg_match('/\}$/' , $line))
    {
      $res = json_decode($line, true);
      if($res["id_str"])
      {
        echo $res["id_str"] . ":";
        echo $res["user"]["screen_name"] . ":";
        echo $res["text"] . "\n";
      }
      $line = "";
    }
  }
  fclose($fp);
}

トラックバック(0)

トラックバックURL: http://horliy.seri.gr.jp/MTcgi/mt-tb.cgi/24

コメントする

このブログ記事について

このページは、ほーりーが2015年4月11日 12:28に書いたブログ記事です。

ひとつ前のブログ記事は「MCLK出力対応Volumio1.55」です。

次のブログ記事は「Volumio1.55 改造 しょの2」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。