週末プログラミングの時間がやってまいりました。
現在、僕は各種SNSのタイムラインをログに残すというサービスを開発中なんですが、その一部をご紹介します。
前提としてfacebookに買収されたinstagramですが、広告配信を開始したりとアドテクの分野でも話題に上がるようになってきており、無視できない媒体になっています。(instagramがなぜ広告モデルを始めたのか、それは別ページでご紹介させていただきます。)
なぜVineはInstagramやSnapchatになれなかったか-Twitterが6秒動画のVineのサービス終了を発表
instagramのapiを弄って利用したいと考えているウェブ系の方は多いと思います。
ただし、最近apiの実装が可能になったこともありまだまだ検索しても情報は少ないです。
僕が行っている実装方法等をまとめます。(oauth認証からタイムライン取得まで。)
ちなみに、instagram api自体は非常に取り扱いやすい仕様になっていて、好感が持てます。facebook apiはイマイチ使いづらいような気がするのですが、僕だけでしょうか。
【WordPress】Facebook ogpとTwitter Cardをプラグイン無しで実装する
instagram apiを使ってタイムラインを表示してみよう
Railsの場合、便利なgemファイルがあるので、以下を入れておきましょう。(Rails 4.2.4, ruby 2.0.0p645 (2015-04-13 revision 50299) [universal.x86_64-darwin15])
Gemfileの中身
## instagram api 関連## gem 'instagram' ## http関連。サーバー側とrest fulにやり取り可能。 ## gem 'rest-client' ## uri関連。api叩いて受け取るデータ形式がjsonなので。 ## gem 'json'
コメントに書いてある通りですが、説明を。
どのSNS apiでもそうですが、所定のURLにpostでアクセストークンなどを載せてリクエストを送ればjsonが返ってくるという仕様になっています。
なので、上記gemを導入しているとRailsの場合実装が非常に簡単になります。
instagram.rbを設定しておく(/config/initializers/instagram.rb)←名称はinstagram.rbにしないとダメ!
require "instagram" Instagram.configure do |config| config.client_id = "あなたのclient id" config.client_secret = "あなたのclient secret" end
client id, client secretって何ぞ?という方も多いと思います。
こちらはinstagramの開発用アカウント(https://instagram.com/developer/)からアプリケーションを登録することで取得することができます。
リンク先を表示して、Manage Clientsのタブをクリックし、新規登録することで簡単に作成できます。
上記画面のclient idとclient secretを先ほどのinstagram.rbに貼り付けましょう。
routes.rbはこんな感じ(/config/routes.rb)
Rails.application.routes.draw do get 'instagram/timeline' root 'home#index' get "home/index" # instagram routes get "/auth/instagram" => "instagram#token" get "/auth/instagram/connect" => "instagram#get_token_timeline" get "/signout_instagram" => "sessions#destroy" # Oauth routes get "/auth/:provider/callback" => "sessions#create" end
※Railsのrest fulなルーティング設定に関してはよく分かっていないので、もっと良い設定絶対あります。
上記設定は、instagram_controller.rbの中身も確認した上でご自身の設計に合わせて設定してください。
application.html.erbは適当に。(/view/layouts/application.html.erb)
<!DOCTYPE html> <html> <head> <title>SocialLog</title> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> </head> <body> <div id="container"> <div id="user_nav"> <%= link_to "instagramにサインイン", "/auth/instagram" %> </div> <%= yield %> </div> </body> </html>
リンク先URLは、/auth/instagramというpathで設定しましょう。
これはapiリファレンスを見れば分かりますが、instagram側でgetで上記pathにリクエストを送ることで、アクセストークン発行用のURlにリダイレクトされます。
ちなみにhtmlに関してはクソ適当です。気にしないでください。
セマンティックWebに準拠したHTML5の基本構造と間違いやすいポイント
以下でapiの処理部分の内容について記述したファイルの中身を見てみましょう。
instagram_controller.rbでほとんどの処理をさせる
class InstagramController < ApplicationController require "instagram" require "json" require "rest-client" ## access_token発行用のURLへのリダイレクト。instagra-ruby-gemのauthorize_urlメソッドを使っています。 def token connect_url = "http://localhost:3000/auth/instagram/connect" redirect_to Instagram.authorize_url(:redirect_uri => connect_url) and return end ## postで所定のURLに情報を送信し、返ってきたjsonからaccess_tokenを取得し、タイムラインを表示する def get_token_timeline connect_url = "http://localhost:3000/auth/instagram/connect" ## 下記要素をpostで送ると、access_tokenを含んだjsonが返ってきます。 res = RestClient.post 'https://api.instagram.com/oauth/access_token', { client_id: 'あなたのclient_id', client_secret: 'あなたのclient_secret', grant_type: 'authorization_code', redirect_uri: connect_url, code: params[:code] } json = JSON.parse(res.body) token = json['access_token'] ## jsonにはuser_idのデータも含まれます。 ## user_id = json['user']['id'] でuser_idを取得すると、該当するユーザーのタイムラインを取得できます。 ## 今は自分のタイムラインを表示するので使いません。 ## タイムラインの取得には、下記URLにgetでリクエストを送りましょう。 feed_url = "https://api.instagram.com/v1/users/self/feed?access_token=" ## タイムラインの投稿取得数を指定できます。上限100のはず。 count = "&count=100" get_feed_url = feed_url + token + count uri = URI.parse(get_feed_url) http = Net::HTTP.new(uri.host, uri.port) ## ここ落とし穴なんですが、instagram apiはSSL通信を前提としているので、httpsで通信するように記述しないとjsonデータが返ってきません。 http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE req = Net::HTTP::Get.new(uri.request_uri) res = http.request(req) ## 後はjsonのデータを取得するだけ。 feed_json = JSON.parse(res.body) puts feed_json end end
本当はdeviseを用いたoauth認証にするのがイケてると思いますが、僕の開発中のサービスは都度タイムラインをapi叩いて取得するため、deviseを導入する意味がありません。
結果、sessionにaccess_tokenをぶち込むという謎設計になっています。。
sessions_controller.rbも一応作っておいた。
class SessionsController < ApplicationController def create if(request.path_info == "/auth/instagram/callback") auth = request.env["omniauth.auth"] session[:instagram_oauth_token] = auth.credentials.token redirect_to "/instagram", :notice => "サインイン!" else redirect_to root_url end end def destroy session[:instagram_oauth_token] = nil redirect_to root_url, :notice => "サインアウト!" end end
これは開発中のサービスの状況に合わせて柔軟に設定変更してください。
そんなに謎な実装をせずに、自分のタイムラインを表示させることができます。
ちなみに二次元配列(連想配列)に投稿の要素を格納したいのですが、知識不足でイマイチ分かっておらず・・分かり次第更新します。
ここまでお読みいただき、ありがとうございます!
未経験の僕がRuby on Railsをここまで扱えるようになったのは「TechAcademy」のおかげです。
僕はアドテクに関するお仕事をしていますが、学生時代の専攻が情報系であったこともありません。
しかし、ここまでコードを書けるようになったのは「TechAcademy」というプログラミングスクールのカリキュラム取り組んだおかげです。
気になる方はぜひ、以下記事を御覧くださいね。