clojureからtwitter4jを使う
春休みなのでtwitterクライアント作ります。
手始めにストリーミングAPIでユーザーストリームを取得しました。
手順は以下
1. project.cljにtwitter4j使えるようゴニョゴニョ書く
clojarsとか覗くとtwitter4jのラッパーっぽいライブラリもあったけど、clojureからtwitter4jを直接叩こうと思います。
project.cljに以下を追加
[org.twitter4j/twitter4j-core "[3.0,)"]
[org.twitter4j/twitter4j-stream "[3.0,)"]
[org.twitter4j/twitter4j-async "[3.0,)"]
2. ConsumerKeyやらAccessTokenやら設定してやってConfigurationBuilderを作る
コード書いてきます。
twitter4jのコード例を眺めると最初にConsumerKeyなどの設定が必要なようです。
具体的な設定はここに書いてありました。
今回はWebページの2番のConfigurationBuilderを用いてプログラムから設定しようと思います。
(def consumerKey "******************************")
(def consumerSecret "***************************")
(def accessToken "******************************")
(def accessTokenSecret "************************")
(defn make-configurationBuilder []
(-> (doto (new ConfigurationBuilder)
(.setDebugEnabled true)
(.setOAuthConsumerKey consumerKey)
(.setOAuthConsumerSecret consumerSecret)
(.setOAuthAccessToken accessToken)
(.setOAuthAccessTokenSecret accessTokenSecret))
(.build)))
consumeKeyやらaccessTokenはTwitter Developpersであらかじめ取得しました。
3. UserStreamListenerを定義してやる
UserStreamListenerはタイムラインをストリームで取得していくなかで、新しいツイートを取得したり、ふぁぼられたり、そういう各イベントが起こったときにあれやれこれやれと設定しておくクラス、だと思います。多分。
とりあえず新しいツイートを取得したらスクリーンネームとツイートを表示するように設定しました。
onStatusってところがそうです。
(def listener
(reify
UserStreamListener
(onStatus [this status]
(println (-> (-> status (.getUser)) (.getScreenName)))
(println (-> status (.getText)))
(println))
(onDeletionNotice [this statusDeletionNotice] nil)
(onTrackLimitationNotice [this numberOfLimitedStatuses] nil)
(onScrubGeo [this userId upToStatusId] nil)
(onStallWarning [this warning] this)
(onFriendList [this friendIds] nil)
(onFavorite [this source target favoritedStatus] nil)
(onUnfavorite [this source rarget favoritedStatus] nil)
(onFollow [this source followedUser] nil)
(onDirectMessage [this directMessge])
(onUserListMemberAddition [this addedMember listOwner alist] nil)
(onUserListSubscription [this subscriver listOwner alist] nil)
(onUserListUnsubscription [this subscriber listOwner alist] nil)
(onUserListCreation [this listOwner alist] nil)
(onUserListUpdate [this listOwner alist] nil)
(onUserListDeletion [this listOwner alist] nil)
(onUserProfileUpdate [this updateUser] nil)
(onBlock [this source blockedUser] nil)
(onUnblock [this source unblockedUser] nil)
(onException [this ex] nil)))
UserStreamListenerはインタフェースで具体的な実装は無いのでreifyマクロでメソッドを定義してやれば良いっぽいです。
※onStatusメソッドだけ定義してやれば表示はするのだけど、たとえばストリーミングでツイート取得しているときにどれかのツイートがふぁぼられたりすると例外吐いて止まってしまったので、とりあえずすべてのメソッドにnilを返すようにしてます。
4. TwitterStreamFactoryクラスのインスタンスを作成する
ストリーミングするのに必要な設定やクラスは用意ができたのでそれらをTwitterStreamFactoryクラスになげつけてやればストリーミングでツイートが取得できます。
(defn make-twitterStream []
(-> (new TwitterStreamFactory (make-configurationBuilder)) (.getInstance)))
(defn -main []
(let [twitterStream (make-twitterStream)]
(-> twitterStream (.addListener listener))
(-> twitterStream (.user))))
こんな感じ。
全体通すとこんな感じ。
(ns ronyatter-clj.core
(:require clojure.string)
(:import [twitter4j TwitterFactory TwitterStreamFactory StatusListener StatusAdapter UserStreamListener])
(:import [twitter4j.conf ConfigurationBuilder]))
(def consumerKey "kI2ijJO8ODuWZ819Zrk7Q")
(def consumerSecret "IQ70vDqXVIthJmV70ieb1RNMdpP0YpYj191HgHZjKyM")
(def accessToken "107718872-9Jiv5HhdrOeh3NtAP3Dt1vMVErKe5MWTmVaXRlmZ")
(def accessTokenSecret "jECQWJ0Palrnxd9egf27ywSPgiagE46xMIH9MR9up7xlP")
(defn make-configurationBuilder []
(-> (doto (new ConfigurationBuilder)
(.setDebugEnabled true)
(.setOAuthConsumerKey consumerKey)
(.setOAuthConsumerSecret consumerSecret)
(.setOAuthAccessToken accessToken)
(.setOAuthAccessTokenSecret accessTokenSecret))
(.build)))
(def listener
(reify
UserStreamListener
(onStatus [this status]
(println (-> (-> status (.getUser)) (.getScreenName)))
(println (-> status (.getText)))
(println))
(onDeletionNotice [this statusDeletionNotice] nil)
(onTrackLimitationNotice [this numberOfLimitedStatuses] nil)
(onScrubGeo [this userId upToStatusId] nil)
(onStallWarning [this warning] this)
(onFriendList [this friendIds] nil)
(onFavorite [this source target favoritedStatus] nil)
(onUnfavorite [this source rarget favoritedStatus] nil)
(onFollow [this source followedUser] nil)
(onDirectMessage [this directMessge])
(onUserListMemberAddition [this addedMember listOwner alist] nil)
(onUserListSubscription [this subscriver listOwner alist] nil)
(onUserListUnsubscription [this subscriber listOwner alist] nil)
(onUserListCreation [this listOwner alist] nil)
(onUserListUpdate [this listOwner alist] nil)
(onUserListDeletion [this listOwner alist] nil)
(onUserProfileUpdate [this updateUser] nil)
(onBlock [this source blockedUser] nil)
(onUnblock [this source unblockedUser] nil)
(onException [this ex] nil)))
(defn make-twitterStream []
(-> (new TwitterStreamFactory (make-configurationBuilder)) (.getInstance)))
(defn -main []
(let [twitterStream (make-twitterStream)]
(-> twitterStream (.addListener listener))
(-> twitterStream (.user))))
(-main)
実行例
何故か二重出力・・・。 この記事みたひとで原因わかるひといたらおしえてくだちぃ。
2013.02.14追記
二重出力の原因はmainが二重で実行されてたせい。
一番最後の(-main)っていう記述がいらないんですね。