こんにちは!村井と申します。
見出しの通りですが、Akka Schedulerの定期実行を使ってInstagramから画像を取得し、
Tumblrへ自動投稿をしたいと思います。
Akkaの設定
Akkaとは
そもそもAkkaですが、
Scala/Javaで非同期処理を実現するためのライブラリで、
Scalaの開発元であるTypesafe社が中心となって開発しています。
Akkaは軽量な並列処理のためのActorモデルをベースとしており、
分散/並列/耐障害性を持ったイベント駆動型アプリケーションを構築できます。
akka-quartz-schedulerというライブラリを使用すれば、
cronのような記述で指定時間に処理を実行することが出来ます。
今回、playframeworkにこのライブラリを入れて、
自動的にブログ(Tumblr)にInsta画像を貼っていきたいと思います。
- build.sbtに設定
libraryDependencies += "com.enragedginger" %% "akka-quartz-scheduler" % "1.4.0-akka-2.3.x"
- application.confに時間を設定
akka { quartz { defaultTimezone = "Asia/Tokyo" schedules { AutomationBlog { description = "3時間ごとに実行" expression = "0 0 0-23/3 ? * *" } } } }
そんなに頻繁に動くものを考えていないので、3時間に1回のスケジュールにしています。
設定方法はほぼcronと一緒ですが、こちらを参考にどうぞ。
class GetInstagramImageCreateTumblr extends Actor { def receive = { case msg: String => val instaImgUrl = GetHashTagImage val tumblrResponce = CreateBlog(instaImgUrl) } }
長ったらしいファイル名にしてますが、スルーでw
GetHashTagImageはInstaから画像を取得しており、
CreateBlog(instaImgUrl)で画像URLをTumblrに投稿しています。
- Globalオブジェクトを用意
object Global extends GlobalSettings { val system = ActorSystem("SampleSystem") val actor = system.actorOf(Props(classOf[GetInstagramImageCreateTumblr])) override def onStart(app: Application) = { QuartzSchedulerExtension(system).schedule("AutomationBlog", actor, "") } override def onStop(app: Application) = { system.shutdown() } }
GlobalオブジェクトのonStartで定期実行の処理を開始させます。
AutomationBlogとありますが、これはapplication.confで指定したスケジュール名と一致させる必要があります。
これで設定は完了です。
activator runをすれば、GlobalのonStartでスケジューラーが動作します。
InstagramAPI
アプリ登録とアクセストークンの取得
さて、Instagramから画像を取得します。
それにはまずAPIを叩きますが、そのためにアプリ登録してアクセストークンが必要になります。
その辺は説明が長くなりすぎるので、
こちらのアプリ登録とアクセストークンの取得を参考にしてください。画像の取得
Instagramからの画像取得は指定したハッシュタグ画像を1つ取得しようと思います。
今回使用したAPIはこちらです。
private def GetHashTagImage = { // 取得したいハッシュタグを指定 val hashTag = "cat" // 画像取得用のAPI(countで取得したい数を指定) val apiUrl = "https://api.instagram.com/v1/" + "tags/" + hashTag + "/media/recent?count=1&access_token=" + "**************************************************" // WSを使用してリクエストを投げてjsonで受け取る val apiResult = WS.url(apiUrl).get().map { response => response.json } val json = Await.result(apiResult, Duration.Inf) // jsonツリーを解析して画像URLだけ取得 val imageUrl = json \ "data" \\ "low_resolution" map (_ \ "url") val imageUrlStr = imageUrl.map { a => a.get.toString() } // ダブルクォーテーションが含まれてしまうので置換で削除しておく imageUrlStr.head.replace("\"", "") }
一部のみですが、Instaからは以下ような感じでjsonが返ってきます。
今回は画像URLさえあればいいので、imagesのlow_resolutionのurlを取得しています。
"images": { "low_resolution": { "height": 320, "url": "https://scontent.cdninstagram.com/hphotos-xtf1/t51.2885-15/s320x320/e35/12301169_1658230961121023_88910125_n.jpg", "width": 320 }, "standard_resolution": { "height": 640, "url": "https://scontent.cdninstagram.com/hphotos-xtf1/t51.2885-15/s640x640/sh0.08/e35/12301169_1658230961121023_88910125_n.jpg", "width": 640 }, "thumbnail": { "height": 150, "url": "https://scontent.cdninstagram.com/hphotos-xtf1/t51.2885-15/s150x150/e35/12301169_1658230961121023_88910125_n.jpg", "width": 150 } },
TumblrAPI
Instaから画像は取得できました。
あとはTumblrに投稿するだけです。
OAuth認証
今回使用するTumblrAPIはこちらのPhoto Postsです。
投稿はGETメソッドではなくPOSTですね。OAuth認証が必要です。OAuth token取得
TumblrはInstagramやTwitterみたいにブラウザなどからtokenを確認する方法はなく、
token取得用プログラムを叩いて取得してね。となってるそうです。
めんどくさいことこの上ないです。
取得用プログラムを公開してる方もいたのですが、API仕様が変わったようで使えなくなってました。
ですが!
TumblrのApi consoleにログインしてみると、
サンプルプログラムが書かれている箇所にtokenが載っています!
なので、これをコピペして使います。Jumblr
Api consoleのサンプルプログラムの中に、Javaがあります。
JavaではTumblrのOAuth認証のためにJumblrが提供されています。
このライブラリを使用せずにscalaだけでやっちゃおうかと思ったのですが、
せっかくなのでJumblrを使用することにしました。build.sbtにJumblrを設定
libraryDependencies += "com.tumblr" % "jumblr" % "0.0.11"
こちらのMaven Repositoryで最新版を確認して設定してください。
- 投稿する
private def CreateBlog(imageUrl: String) = { val consumerKey = "**************************************************" val consumerSecret = "**************************************************" val client: JumblrClient = new JumblrClient( consumerKey, consumerSecret ) client.setToken( // oauthToken "**************************************************", // oauthTokenSecret "**************************************************" ) // postCreateのparamはjava.util.Mapなので、scalaのMapではなくこちらを使用する val params: java.util.Map[String, String] = new HashMap[String, String]() params.put("type", "photo") params.put("source", imageUrl) client.postCreate("instagramtagimage.tumblr.com", params) }
Jumblrのおかげでめっちゃ簡単ですね。
imageUrlはInstaから取得した画像URLを渡しています。
consumerKey
consumerSecret
oauthToken
oauthTokenSecret
は4に記載している通り、TumblrのApi consoleに記載されているのでコピペしてください。
完成
Tumblrアプリ登録時に作っておいたブログを見てみましょう。
ちゃんと投稿されてますね。
まとめ
Akka schedulerを使わなくてもcronでいいやん。って思われますが、
プログラム含め、Playひとつで完結出来るんで管理もしやすいですね。
他にもTwitterに自動的につぶやいたり、
画像をクローリングして、Pinterestにピンしておいたり、など色々出来ますね。
もちろん、SNS以外にも使えますw
長くなりましたが以上です。
最後まで読んでいただきありがとうございました。