Twitter Streaming APIをPHPで簡単に扱える、phirehoseを紹介します!
目次
こんにちは。
開発チームのワイルド担当、まんだいです。
Twitterって、最近も流行っているのか、もしくはもう既に定着しているのか、この辺はよくわからないですが、Twitter Streaming APIを使って、色々情報収集できればなと思って、かじってみました。
1からプログラムを書くのはさすがにツライということで、便利なライブラリを使ってやってみたところ、すこぶる簡単にできてしまったのでご紹介しようと思います。
Twitter API用のアクセストークンとアクセスシークレットシークレットを取得する
これがなくては、何も始まらないので、ささっと取得してしまいます。
専用のアカウントを取るもよし、既存のユーザーで取得するもよし、というところです。
Twitterにログインしてこちらにアクセスすると、「Create New App」というリンクがありますので、そちらの方から登録します。
Streaming APIは、アクセス回数によるリミットがない(というか、ストリーミングなので、繋ぎっぱなしでデータを取得し続けるイメージ)ので、やりすぎてbanされるような心配はありません。
尤も、疎通できていないのに何度もリトライすると、止められる事はあるようですので、再接続やレスポンス監視などの部分でプログラムを作り込む必要はあります。
作り込むのに時間が掛かるので、今回はそのあたりまでカバーしてくれるライブラリを導入します。
Streaming APIを簡単に利用するphirehoseを導入する
phirehoseは、Twitter Streaming APIとのやり取りをしてくれるPHP用のライブラリです。
これを利用すると、認証から接続、データ取得までやってくれるクラスが揃っているので、サンプルをコピペしてアクセスキーの情報を埋めるだけで、コンソールから実行するとデータがとれます。
githubに公開されているリポジトリなので、git cloneしてくれば、すぐに利用可能です。
# プロジェクト内のディレクトリで git clone https://github.com:fennb/phirehose.git
これだけなので、もう少しStreaming APIのエンドポイントに対応するクラスを紹介したいと思います。
Public Streams
Public Streamsは、Twitter全体のタイムラインからデータを取得するAPIです。
エンドポイントは2つです。
POST statuses / filter
POST statuses / filterは、POSTメソッドで定義されている割には、GETパラメータも読むようになっていたり、割と親切設計なAPI。
TwitterのユーザーID、キーワード、位置情報の3つから読み込むツイートを絞り込みます。
follow (ユーザーID)
フィルターを掛けるユーザーID。
phirehoseでは、setFollow()メソッドから、配列で渡します。
track (キーワード)
フィルターを掛けるキーワード。
phirehoseでは、setTrack()メソッドから、配列で渡します。
location (位置情報)
フィルターを掛ける位置情報。
左下と右上の2点で表現される矩形による選択になりますので、日本国内だけにフィルタリングしようとすると、複数の位置情報を繋げる必要があります。
phirehoseでは、setLocations()メソッドから、配列で渡します。
また、常に2次元配列である必要があり
- 左下(最南西)の経度
- 左下(最南西)の緯度
- 右上(最北東)の経度
- 右上(最北東)の緯度
の順に値を収めた配列を値に持つ配列を引数として渡す事になります。
なので、複数の矩形をいくつもセットする事で、日本国内をカバーした範囲を作成する事が可能です。
その他に、複数の大都市のみをターゲットにフィルタリングしたりする事も可能です。
GET statuses / sample
GET statuses / sampleは、Twitter上の全ツイートから、小数のサンプルをランダムに抽出して取得するAPI。
約1%程度のデータ量らしいですが、それでも勢いはすごいようなので、要注意。
こちらはオプションなしです。
User Streams
一人のユーザーをターゲットに、タイムラインや、プロフィールのアップデート、イベントなどの取得をするAPIです。
このAPIを介して、不特定多数のユーザーアカウントのストリーミングをすると、同一IPアドレスからの接続制限に引っかかる恐れがあるので、別の手を考えます。
また、User Streams APIには、ターゲットユーザーへのリプライや、リツイートなども含めるかでオプションがあります。
※ phirehoseでは、trackオプションには専用メソッドがありますが、with、repliesに関しては専用メソッドがなさそうなのですが、User Streams APIは今回使用しなかったため設定方法まで調査していないため、言及しません(Twitterが提供しているドキュメントの訳のみになります)。
with (ユーザーがフォローしている別アカウントの扱い)
デフォルトでは、「with=followings」となっているので、ユーザーと、そのユーザーがフォローしているユーザーのデータがストリームに入ってきます。
「with=user」とすると、アカウントユーザーのデータのみになります。
replies (リプライの扱い)
デフォルトでは、ユーザー同士がフォロワー同士の状態のリプライのみがストリームの対象になっていますが、「replies=all」とすることで、リプライ全てを受信する事ができます。
track (キーワードによる追加のツイート)
trackを設定する事で、キーワードにマッチするツイートを追加でストリームの対象とすることができます。
Site Streams
現在(結構前から)ベータ扱いのSite Stream APIですが、こちらは User Streams APIが1ユーザーのタイムラインなのに対して、複数のユーザーのタイムラインを一つのストリームの中に合わせて流すというものになります。
ベータ版らしく、色々制限がありますが、以下のような制限になります。GAになる日は来るのでしょうか?
- 1回の接続で100ユーザー分のタイムライン(だけではなく、プロフィールの更新情報などのデータも配信)。Control Streamsを使って、最大1000ユーザーまで増やせる
- 最大25コネクション/秒。コールしすぎたり等でエラーが発生した場合に備えて、exponentially back-off(指数関数的衰退)を実装する必要があります
- 約1000件を越える接続を開く場合、Twitter Platform teamとともにテストやローンチの調整をする必要があります(Twitter Platform Teamが何を意味するものか、調べましたが分からず。Twitter内部のチームでしょうか? かなり不安のある訳なので、鵜呑みにしないでください)。
取得できるJSONデータのサンプル
取得したJSONデータのサンプルは以下のような感じです。
1件あたりのデータが割と大きめで、色んなデータが取れます。
array(25) { ["created_at"]=> string(30) "Mon Mar 27 04:41:07 +0000 2017" ["id"]=> float(0.000000000000E+17) ["id_str"]=> string(18) "0000000000000000" ["text"]=> string(78) "xxxxxxxxxxxxxxxx" ["source"]=> string(82) "xxxxxxxxxxxxxxxx" ["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) "0000000000" ["name"]=> string(13) "xxx xxx" ["screen_name"]=> string(8) "xxxxxxxx" ["location"]=> string(27) "xxxxxxxxxxxxxxxx" ["url"]=> NULL ["description"]=> string(135) "xxxxxxxxxx" ["protected"]=> bool(false) ["verified"]=> bool(false) ["followers_count"]=> int(669) ["friends_count"]=> int(533) ["listed_count"]=> int(1) ["favourites_count"]=> int(2267) ["statuses_count"]=> int(3727) ["created_at"]=> string(30) "Fri Mar 20 09:23:52 +0000 2015" ["utc_offset"]=> NULL ["time_zone"]=> NULL ["geo_enabled"]=> bool(true) ["lang"]=> string(2) "ja" ["contributors_enabled"]=> bool(false) ["is_translator"]=> bool(false) ["profile_background_color"]=> string(6) "C0DEED" ["profile_background_image_url"]=> string(48) "xxxxxxxxxxxx" ["profile_background_image_url_https"]=> string(49) "xxxxxxxxxxxx" ["profile_background_tile"]=> bool(false) ["profile_link_color"]=> string(6) "1DA1F2" ["profile_sidebar_border_color"]=> string(6) "C0DEED" ["profile_sidebar_fill_color"]=> string(6) "DDEEF6" ["profile_text_color"]=> string(6) "333333" ["profile_use_background_image"]=> bool(true) ["profile_image_url"]=> string(74) "xxxxxxxxxx" ["profile_image_url_https"]=> string(75) "xxxxxxxxxx" ["profile_banner_url"]=> string(59) "xxxxxxxxxx" ["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) "5ab538af7e3d614b" ["url"]=> string(56) "https://api.twitter.com/1.1/geo/id/5ab538af7e3d614b.json" ["place_type"]=> string(4) "city" ["name"]=> string(16) "横浜市 旭区" ["full_name"]=> string(23) "神奈 横浜市 旭区" ["country_code"]=> string(2) "JP" ["country"]=> string(6) "日本" ["bounding_box"]=> array(2) { ["type"]=> string(7) "Polygon" ["coordinates"]=> array(1) { [0]=> array(4) { [0]=> array(2) { [0]=> float(139.488892) [1]=> float(35.440878) } [1]=> array(2) { [0]=> float(139.488892) [1]=> float(35.506665) } [2]=> array(2) { [0]=> float(139.570535) [1]=> float(35.506665) } [3]=> array(2) { [0]=> float(139.570535) [1]=> float(35.440878) } } } } ["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) "low" ["lang"]=> string(2) "ja" ["timestamp_ms"]=> string(13) "1490589667759" }
まとめ
Twitter APIはOAuth認証の実装めんどくさいとか、今では普通になりましたが、アクセストークンの扱いだとかで、過去には色々実装しなければいけなかったものが多かったですが、5分と言わずとも、いくら悩んでも1時間あれば、自分の納得がいくデータが取れるだけのライブラリがあるのはうれしいですね。
以上です。