【TwitterAPI+PHP】Phorehoseを使ってTwitter Streaming APIでリアルタイムに超膨大なツイートを取得する
こんにちは。今回はPHPのライブラリ「Phirehose」を使って文章解析用データcorpusを作成してみようって記事です。
特定ワードを設定するとリアルタイムにTwitter Streaming APIからデータが送られてきます。
嘗てはUser streamっていう種類もあったんですが提供終了しまいた。
取り敢えずサンプルコードを見て学べ!ってことで早速実装しましょう。
Phirehoseをダウンロード
今回は先述したとおりPhirehoseっていうPHPライブラリを使用します。TwitterAPIを操るライブラリはTwistOauthやAbraham/TwitterOauthが有名ですがストリーミングAPIには対応してないのでPhorehoseを使います。
Composerを使ってでもインストール出来ます。ですが今回は手っ取り早くGitからパクります。cloneしてください。
git clone https://github.com/fennb/phirehose
これで導入は終わりです。早速コードを書いていましょう。
因みにPhirehoseって言うなの由来はStreamingAPIの種類に大企業専門、とんでもない額がかかるらしいfirehoseっていう奴がありそれをもじったものらしいです。
コードを実装
以下が特定ワード(複数指定可)を含むツイートを付加情報を付けてCSVファイルにエクスポートするコードです。
<?php // タイムアウトしないように… set_time_limit(0); // ライブラリを読み込む(適宜ディレクトリを変更してください) require_once('lib/Phirehose.php'); require_once('lib/OauthPhirehose.php'); class FilterTrackConsumer extends OauthPhirehose { public function enqueueStatus($status) { // ここの関数内で受信時の処理を書いていきます $data = json_decode($status, true); if (is_array($data) && isset($data['user']['screen_name'])) { $text = preg_replace('/[\n\r\t]/', '', $data['text']); $timeline = $data["id_str"] . "," . $data['user']['screen_name'] . ',' . $data['created_at'] . ',' . urldecode($text) . ",\n"; echo $data["id_str"]; // 確認のためIDを出力しています $timeline = mb_convert_encoding($timeline, 'SJIS-win', 'ASCII, JIS, UTF-8, SJIS'); file_put_contents("sample.csv", $timeline, FILE_APPEND); } } } // APIの情報を定義 define("TWITTER_CONSUMER_KEY", "*******************************"); define("TWITTER_CONSUMER_SECRET", "***************************************************"); define("OAUTH_TOKEN", "************************************************"); define("OAUTH_SECRET", "*********************************************"); // 実行 $sc = new FilterTrackConsumer(OAUTH_TOKEN, OAUTH_SECRET, Phirehose::METHOD_FILTER); $sc->setTrack(array('keyword1', 'keyword2')); $sc->setLang('ja'); // 日本語指定 $sc->consume();
とても手短で簡単に実装できますね。一応Gistにもあげときます~
コード解説
べつに解説することもないんですけど…
単純にFilterTrackConsumerクラスのenqueueStatus関数の中に受信してきたデータをどう処理するかを書いて行きます。
そしてAPIの認証情報を定義してキーワードやリージョン・位置情報を指定したあと$sc->consume();で取得開始。
Windowsの場合の注意
Windowsで操作したいならファイル書き込みの際必ずSJIS-winでエンコードしてください。
Excelとかメモ帳で開くとバグります。文字化けね。なかなか治らなくなるのでご注意を…
$timeline = mb_convert_encoding($timeline, 'SJIS-win', 'ASCII, JIS, UTF-8, SJIS');
まぁmb_convert_encoding()関数で一発ですが。第3関数を”auto”じゃまずいらしいので一応全部選択してみました。
注意事項
何故かStreamingAPIはエラーに厳しいです。
なのであまり失敗しないように…って言うわけにも行かないと思いますがもしHTTP Errorとか言われたらAPI KeyとAccess Token Secretを再生成したら治ります。
+α ブラウザから取得したい場合
ターミナルシェル上以外のブラウザとかで取得したいなら次のコードをさっきのなんとか関数に追記してください。
ob_flush(); flush();
これはサーバーとの通信中でも逐次画面上に表示するために書くやつです。StreamingAPIは常にTwitterと通信をしっぱなしで取得するため(XMLHttpRequestのxhr.ReadyState 3の通信中みたいな感じ。)こういう処理が必要です…
※ターミナル上で↑を付けたままやるとエラー返されます。
サンプルデータ
一昨日あったシャニマスの福岡公演のハッシュタグをキーワードにセットして約12万件のツイートがCSV形式で取得できました
浮動小数点がある型(float)で保存してしまったからツイートIDがミスっちゃってます…まぁ良いでしょう。
ダウンロードは↓から。リンク切れはお問い合わせフォームからお願いします。コメントでは対応しません。
受信されるJSONデータ型
APIから帰ってくるツイートデータのJSONを配列に変換したやつを掲載します。
一個一個紹介してられないのでまぁご自分で確認してください…
array(25) { ["created_at"]=> string(30) "" ["id"]=> float(0.000000000000E+17) ["id_str"]=> string(18) "" ["text"]=> string(78) "" ["source"]=> string(82) "" ["truncated"]=> bool(false) ["in_reply_to_status_id"]=> NULL ["in_reply_to_status_id_str"]=> NULL ["in_reply_to_user_id"]=> NULL ["in_reply_to_user_id_str"]=> NULL ["in_reply_to_screen_name"]=> NULL ["user"]=> array(38) { ["id"]=> float(0000000000) ["id_str"]=> string(10) "" ["name"]=> string(13) "" ["screen_name"]=> string(8) "" ["location"]=> string(27) "" ["url"]=> NULL ["description"]=> string(135) "" ["protected"]=> bool(false) ["verified"]=> bool(false) ["followers_count"]=> int() ["friends_count"]=> int() ["listed_count"]=> int() ["favourites_count"]=> int() ["statuses_count"]=> int() ["created_at"]=> string(30) "" ["utc_offset"]=> NULL ["time_zone"]=> NULL ["geo_enabled"]=> bool(true) ["lang"]=> string(2) "" ["contributors_enabled"]=> bool(false) ["is_translator"]=> bool(false) ["profile_background_color"]=> string(6) "" ["profile_background_image_url"]=> string(48) "" ["profile_background_image_url_https"]=> string(49) "" ["profile_background_tile"]=> bool(false) ["profile_link_color"]=> string(6) "" ["profile_sidebar_border_color"]=> string(6) "" ["profile_sidebar_fill_color"]=> string(6) "" ["profile_text_color"]=> string(6) "" ["profile_use_background_image"]=> bool(true) ["profile_image_url"]=> string(74) "" ["profile_image_url_https"]=> string(75) "" ["profile_banner_url"]=> string(59) "" ["default_profile"]=> bool(true) ["default_profile_image"]=> bool(false) ["following"]=> NULL ["follow_request_sent"]=> NULL ["notifications"]=> NULL } ["geo"]=> NULL ["coordinates"]=> NULL ["place"]=> array(9) { ["id"]=> string(16) "" ["url"]=> string(56) "" ["place_type"]=> string(4) "" ["name"]=> string(16) "" ["full_name"]=> string(23) "" ["country_code"]=> string(2) "" ["country"]=> string(6) "" ["bounding_box"]=> array(2) { ["type"]=> string(7) "" ["coordinates"]=> array(1) { [0]=> array(4) { [0]=> array(2) { [0]=> float() [1]=> float() } [1]=> array(2) { [0]=> float() [1]=> float() } [2]=> array(2) { [0]=> float() [1]=> float() } [3]=> array(2) { [0]=> float() [1]=> float() } } } } ["attributes"]=> array(0) { } } ["contributors"]=> NULL ["is_quote_status"]=> bool(false) ["retweet_count"]=> int(0) ["favorite_count"]=> int(0) ["entities"]=> array(4) { ["hashtags"]=> array(0) { } ["urls"]=> array(0) { } ["user_mentions"]=> array(0) { } ["symbols"]=> array(0) { } } ["favorited"]=> bool(false) ["retweeted"]=> bool(false) ["filter_level"]=> string(3) "" ["lang"]=> string(2) "" ["timestamp_ms"]=> string(13) "" }