酒と泪とRubyとRailsと

Ruby on Rails と Objective-C は酒の肴です!

Heroku Mongolab + RubyでTwitter Stream APIの JSONを保存【Eventmachine】

TwitterのStreaming APIを色々といじっています。今回はMongoLabがJSONをそのまま保存できるというのを最近おしえてもらったので、勉強がてらMongoLabを触ってみました。

また、この機会にRubyのEventMachineについても多少勉強したり、資料をさがしてみたのであわせて ご紹介いたしやす!


Mongoの基本を学ぶ

MongoDBの基本は、安定のドットインストールで!

あとは英語ですが、MongoDB Ruby Driver Tutorialを読めば最低限の操作は理解できそう。

Eventmachineの基本を学ぶ

RubyのEventMachineですが、海外の入門PDFをナイスに翻訳してくれているこちらが一番オススメ。

こちらはEventMachineを使ったアプリの一例。なかなか悪くない!

サンプルソース

Gemfile

まずは今回使ったGemfile。

1
2
3
4
5
6
7
8
9
10
11
ruby '2.1.0'

source 'https://rubygems.org'

gem 'tweetstream'
gem 'eventmachine'
gem 'mongo'
gem 'bson'
gem 'bson_ext'
gem 'foreman'
gem 'dotenv'

Twitter Stream API => MongoDBのソース

Twitter Stream API から 取得したJSONをそのままMongoDBに保存するまでのRubyのソースコードです。

おおまかなプログラムの流れはこちら。

(1) MongoDBからFollowersの一覧を取得
(2) Twitter Stream APIでFollowersを監視
(3) Tweetが流れてきたらMongoDBにJSONをそのまま保存
(4) Followersが増えたらworkerをエラー終了(herokuでworkerとして起動した場合は、エラー終了しても再起動してくれる)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
require 'rubygems'
require 'bundler'

Bundler.require
Dotenv.load unless ENV['MONGODB_URL']

# MONGODBへの接続
connection = Mongo::Connection.from_uri(ENV['MONGODB_URL'])
@db = connection.db(ENV['DB_NAME'])
@db.authenticate(ENV['USER_NAME'], ENV['PASSWORD'])
@tweets = @db.collection('tweet')

# (1) MongoDBからFollowersの一覧を取得
def get_followers_id
  @followers = @db.collection('follower')
  @followers.find().map{|f| f['id'].to_i }
end
@followers_id_list = get_followers_id

TweetStream.configure do |config|
  config.consumer_key = ENV['TWITTER_CONSUMER_KEY']
  config.consumer_secret = ENV['TWITTER_CONSUMER_SECRET']
  config.oauth_token = ENV['TWITTER_OAUTH_TOKEN']
  config.oauth_token_secret = ENV['TWITTER_OAUTH_TOKEN_SECRET']
  config.auth_method = :oauth
end

@count = 0
EM.run do
  client = TweetStream::Client.new

  # (3) Tweetが流れてきたらMongoDBにJSONをそのまま保存
  def write_to_mongodb(status)
    EM.defer do
      $stdout.print "status: #{status}\n"
      $stdout.flush

      # tweetを保存
      @tweets.insert({status: status})
    end
  end

  # (2) Twitter Stream APIでFollowersを監視
  client.follow(@followers_id_list) do |status|
    write_to_mongodb(status)
  end

  # (4) Followersが増えたらworkerをエラー終了
  EM::PeriodicTimer.new(ENV['FOLLOWER_CHECK_INTERVAL']) do
    new_followers_id_list = get_followers_id
    EM.stop if new_followers_id_list and new_followers_id_list != @followers_id_list
  end
end

今回は、Twitter-Stream-API用Gemに『tweetstream/tweetstream』を使いました。アップデートの頻度が高いことと、説明が充実していたからです。

.envの読み込みをしてくれる『dotenv』を初めて知って使いました。pryでデバックするのを助けてくれます。

あとログを残したいのでAddonを検討中。Pure Rubyでログを残すときにおすすめの方法とかあればぜひ教えて下さい。

Procfile

今回のProcfileはこちら。

1
worker: bundle exec ruby tweet_stream_to_mongodb.rb

今回はプロセス名をworkerにしました。workerの場合は異常終了した場合に、再起動をしてくれるそう。初めて知りましたが、これはtwitter stream APIのように通信の失敗などでこけることがあるプロセスにはほんとうに嬉しい仕様。

Special Thanks

Elämä on — 実質無料!Rubyで作りMongoDBで保存しHerokuで運用するコスパ最強のTweet収集方法

.env: Twitterのキー情報の取得と環境変数への登録

まずは以下のサイトでTwitterアプリを登録してください。
(Sign in => アプリの登録)

Twitter Developers

登録したら環境変数にTwitterキーを登録します。まずはローカルへのキー情報の登録です。foremanで管理しているプロセスでは、.envファイルに環境変数にしたい情報を書き込むと勝手に読み込んでくれます。

1
2
3
4
TWITTER_CONSUMER_KEY=xxx
TWITTER_CONSUMER_SECRET=xxx
TWITTER_OAUTH_TOKEN=xxx
TWITTER_OAUTH_TOKEN_SECRET=xxx

.env: MongoDBの接続設定

まずはMongoDBでDBとユーザーを作成。

1
2
3
4
5
6
mongo
use db_name
db.addUser("user_name","password");

db.auth('user_name','password')
#> 1 # <= となっていれば成功

次に、localhostでのMongoDBの接続設定。DB_NAME, USER_NAME, PASSWORDを入力して登録。

1
2
3
4
MONGODB_URL=mongodb://localhost
DB_NAME=xxxx
USER_NAME=xxxx
PASSWORD=xxxx

Special Thanks

mongodbユーザ認証有効化 - Studio3104::BLOG.new

Herokuへのデプロイ

では、Herokuにソースコードをデプロイ。
(このまえにソースはローカルでgitにコミットしておいてください)

1
2
heroku create APP --stack cedar
git push heroku master

続いてMongoLabのAddonを追加。

1
heroku addons:add mongolab

次のコマンドで接続情報をブラウザで見れるので、その情報をherokuの環境変数に登録。

1
heroku addons:open mongolab

Twitterのキー情報やDBへの接続情報もherokuの環境変数に登録。

1
2
3
4
heroku config:set TWITTER_CONSUMER_KEY=xxx
heroku config:set TWITTER_CONSUMER_SECRET=xxx
heroku config:set TWITTER_OAUTH_TOKEN=xxx
heroku config:set TWITTER_OAUTH_TOKEN_SECRET=xxx

workerプロセスを起動!

1
heroku scale worker=1

ということでHerokuの無料枠の中で、TweetをそのままJSONとして保存できるようになりました!

Special

mongodb-driver-examples/ruby/ruby_simple_example.rb at master · mongolab/mongodb-driver-examples

rubyでmongodbを使ってみる by mongolab - shoprevのブログ

おすすめの書籍