今更ながらTwitterのデータを検索して遊んでいます。Twitterのデータはリアルタイム性がありメタデータも豊富に定義されています。世界中の人が勝手につぶやいてくれるので、属性をもつランダムなテキストデータを簡単に取得できます。最初にNode.jsのCommander.jsで簡単なCLIのインタフェースを用意します。REST APIのGET search/tweetsとStreaming APIのPOST statuses/filterをCLIから試しながらどんなデータが取得できるかプロトタイプします。
プロジェクトと使い方
作成したプロジェクトはリポジトリにpushしています。
$ cd ~/node_apps/node-tweet |
カレントディレクトリにシムリンクを作ってからbuildします。
$ ln -s /dist/node_modules . |
簡単な使い方
README.mdに例があります。GET search/tweetsはREST APIです。以下のように指定すると、babymetal
のキーワードでドイツ語のtweetを10件検索します。検索結果はCSV形式のファイルにして指定したアドレスに添付為てメールします。
$ docker-compose run --rm twitter search "babymetal -filter:retweets" -- -l de -C -e ma6ato@gmail.com |
POST statuses/filterはStreaming APIです。以下のように指定すると、android
のキーワードで英語のtweetをストリームで取得して標準出力します。
$ docker-compose run --rm twitter track android -- -l en |
app.js
app.jsがエントリポイントです。Commander.jsを使いCLIのプログラムを構成します。オプションはGET search/tweetsの仕様に加えて、CSVファイル作成と検索結果をGmailで送信する機能のフラグをつけました。
; |
search.js
search.jsにコマンドを実装します。特に難しいことはしないでtwitのライブラリを実行しています。ここでの目的はTweetデータの中身から使えそうなフィールドを抽出することと、lodashの関数合成や他の関数を試してみることです。
; |
Commander.jsのoptionは難しい
Commander.jsの引数の扱い方はちょっと癖があるので思った通りの引数がうまく取得できません。CLIからオプションが未指定の場合は、action()に指定したコマンドの引数のoptionsにundefinedで入ります。リクエストを発行する関数に渡すparamsのオブジェクトは動的に作成することになります。Conditionally set a JSON object propertyによるとstringifyでJSONを文字列にするときにundefinedなフィールドは作成しないようです。
twitter.jsでもparamsはstringfyしているのでCommander.jsのoptionsはundefinedなフィールドをそのまま渡しました。
var paramsClone = JSON.parse(JSON.stringify(params)) |
--result_type
オプションの場合、オプションが1つだけなら<type>
と記述するとUNIX的に入力が必要なコマンドになります。
$ docker-compose run --rm twitter search "babymetal -filter:retweets" -- --result_type |
ただし複数のオプションがあると必須が効かなくなり意図しない動作をします。以下の場合recent_type
には次のオプションの-l
が入ってしまします。
$ docker-compose run --rm twitter search "babymetal -filter:retweets" -- --result_type -l ja |
また最後の引数にrecent
としてデフォルト値を使う場合、コマンドラインから--recent_type
が未指定でもoptions.result_type
の変数にrecent
が入ってしまいます。未指定の場合はundefined
を意図しているのでこれも困ります。
.option('-r, --result_type [type]','result type','recent') |
試行錯誤すると以下のように[type]
としてデフォルト値を使わないのがよさそうです。
.option('-r, --result_type [type]','result type') |
--result_type
を指定しない場合、options.result_type
はundefined
になるためparamsをstringifyするときには削除されます。
lodashで関数型言語
Node.jsを関数型言語っぽく書くためにlodashを使っています。ほぼこのプログラムを書いた主な目的になっています。APIで取得したTwitterのリストを加工するときに関数型言語のように扱ってみます。
関数合成ができるできるcomposeのflowRightが便利です。以下のようにon('tweet')
のコールバックに_.compose
で関数合成した関数を指定できます。on('tweet')
はコールバックの引数にTweetのデータを渡します。右から順番にextractData
でJSONから必要なフィールドを抽出して、return
をJSON.stringify
に渡し、さらにそのreturn
を標準出力に渡します。
function commandTrack (track,options) { |
gmail.js
このモジュールではNodemailerで添付ファイルをGmailで送信しています。この例ではメールアドレスのバリデーションや、メール本文にTweetのメタデータを追加しています。Nodemailerを使うとGmailの添付ファイル送信がとても簡単に書くことができます。
; |
まとめ
今回のプロトタイプでTwitterのAPIにどのようなパラメータがあり、Tweetデータからどのようなフィールドを取得して加工すると有用なのか使いながらフィードバックを得ることができます。次はジョブをキューしたり、定期的に処理をスケジュール管理できるようにしてみます。