まったりするmatayu

ツイートにゴミがついた感じのブログ

YouTube Data APIを叩いてみる(導入)

備忘録

YouTube  |  Google Developers

このサイトをみると,YouTubeAPIは大まかに

  • Play YouTube Videos

  • Add YouTube Data

  • Analytics & Reporting

  • Subscribe Buttons

  • Live streaming

みたいな5つがあって,

今回はYouTubeから動画のタイトルやLive配信の開始時間(これはLive streamingのほうにあるかも)などのDataをとりたいだけだから,

多分「Add YouTube Data」という API を使えば良いだろう.

上記のサイトから辿れるが次の,

YouTube Data API Overview  |  Google Developers

を参考に進めていく.

Before your start

YouTube Data API を使うにあたっての事前準備事項があるようだ.

  1. Google アカウントの作成.

  2. Google developers consoleにて,プロジェクトの作成.認証情報の取得.

  3. プロジェクトでYouTube Data API v3 がonになっていることを確認.

  4. ユーザー認証を必要としていればOAuth2.0認証の実装.

  5. クライアントライブラリを選択.

  6. JSONをしっかり理解.

まずはこいつらを全部クリアしていく.

1. Googleアカウントの作成

割愛.

2. consoleでプロジェクトの作成と認証情報の取得.

コンソールはここからアクセスできる.

Google Cloud Platform

プロジェクト作成

Google APIs と書いてあるところの右隣にある下三角を押すとウィンドウがポップアップするから,そこで新しいプロジェクトを押す.

そうしたら,そこでプロジェクト名やら組織名やらを入力してプロジェクトを作成する.

(3. )Data API を有効化する

認証情報を作成する前に Data API を有効化しておく.

ダッシュボードタブを選択して, そこでAPI とサービスを有効化を押す.

そこでYouTube Data API v3を探して有効化すればよい.

認証情報の作成

今回はOAuth2.0認証を使用するから,まずOAuth同意画面の設定をする.

OAuth同意画面タブを開いて,質問に答える.

次の画面で必要最低限,アプリケーション名を設定して認証情報の作成に進む.

認証情報タブを選択して,そこで認証情報を作成を押す.

OAuth2.0認証を使用するからOAuthクライアントIDを選ぶ.

そこで必要情報を埋めて,作成する.

作成できたら,OAuth2.0 クライアントIDの一覧から作成したものを選択し,

そこでJSONをダウンロードをクリックしてクライアントの情報が書かれたjsonファイルをダウンロード.

ダウンロードしたものをサーバーの任意の場所に置いておく.

(次のサーバー側のOAuth2.0設定をする時に使う)

4. OAuth2.0認証の実装

ここをメインの参考にOAuth2.0認証のサーバー側の設定やらコードやらを書いた.

Using OAuth 2.0 for Web Server Applications  |  YouTube Data API

使用したものとしては,

のような感じで,サブで参考にしたサイトはこの辺り.

godoc.org

godoc.org

github.com

書いたコードは次のような感じ(一部).

package oauth

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    // mysql is used for gorm.
    _ "github.com/go-sql-driver/mysql"
    "github.com/jinzhu/gorm"
    "github.com/matac42/LiveShare/database"
    "golang.org/x/oauth2"
)

// Conf wraped oauth2.Config.
type Conf struct {
    oauth2.Config
}

// CredentialInfo store oauth2 access token etc...
type CredentialInfo struct {
    gorm.Model
    oauth2.Token
}

// APIInfo include api info from google.
type APIInfo struct {
    Web struct {
        ClientID                string   `json:"client_id"`
        ProjectID               string   `json:"project_id"`
        AuthURI                 string   `json:"auth_uri"`
        TokenURI                string   `json:"token_uri"`
        AuthProviderX509CertURL string   `json:"auth_provider_x509_cert_url"`
        ClientSecret            string   `json:"client_secret"`
        RedirectURIs            []string `json:"redirect_uris"`
        JSOrigins               []string `json:"javascript_origins"`
    }
}

// CreateAPIInfo create APIInfo based on apiinfo.json.
func CreateAPIInfo() APIInfo {
    apiInfo := APIInfo{}
    raw, err := ioutil.ReadFile("/home/ubuntu/Downloads/apiinfo.json")
    if err != nil {
        fmt.Println(err.Error())
    }

    json.Unmarshal(raw, &apiInfo)

    return apiInfo
}

// CreateConf create oauth2 config structure.
func CreateConf() Conf {
    apiInfo := CreateAPIInfo()
    conf := Conf{
        oauth2.Config{
            ClientID:     apiInfo.Web.ClientID,
            ClientSecret: apiInfo.Web.ClientSecret,
            Scopes:       []string{"https://www.googleapis.com/auth/youtube.readonly"},
            Endpoint: oauth2.Endpoint{
                AuthURL:  apiInfo.Web.AuthURI,
                TokenURL: apiInfo.Web.TokenURI,
            },
            RedirectURL: apiInfo.Web.RedirectURIs[0],
        },
    }
    return conf
}

// Google redirect google oathorized page.
func (conf Conf) Google(c *gin.Context) {

    url := conf.AuthCodeURL("state", oauth2.AccessTypeOffline)
    c.Redirect(http.StatusMovedPermanently, url)

}

// CallBack fires fn when there was a connection to /callback.
func (conf Conf) CallBack(c *gin.Context) {
    code := GetAuthCode(c)
    tok := conf.GetAccessToken(c, code)
        cre := CredentialInfo{}
    cre.Token = *tok
    SaveCredentialInfo(cre)
}

// GetAuthCode get credential code from google.
func GetAuthCode(c *gin.Context) string {
    code := c.Request.URL.Query().Get("code")
    err := c.Request.URL.Query().Get("error")
    if err != "" {
        fmt.Println(err)
    }
    // if _, err := fmt.Scan(&code); err != nil {
    //     log.Fatal(err)
    // }

    return code
}

// GetAccessToken get accesstoken from google.
func (conf Conf) GetAccessToken(c *gin.Context, code string) *oauth2.Token {
    tok, err := conf.Exchange(c, code)
    if err != nil {
        log.Fatal(err)
    }

    return tok
}

// SaveCredentialInfo is routines for storing credential info to the database.
func SaveCredentialInfo(cre CredentialInfo) {
    db, err := database.SQLConnect()
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()
    db.AutoMigrate(cre)
    error := db.Create(&cre).Error
    if error != nil {
        fmt.Println(error)
    } else {
        fmt.Println("success addition access token to db!!!")
    }
}

上から見ていくと,

Google()は認証ページへのリダイレクトを行い,CallBack()でgoogleからのcallbackを処理する.

GetAuthCode()はcallbackで返ってきた認証コードを処理し,

そのコードをGetAccessToken()に渡してAccess Tokenを取りにいく.

最後に取って来たAccess TokenをSaveCredentialInfo()でデータベースに保存する.

そんな感じの流れになっている.

一応,今後何らかのweb アプリケーションにすることを考えて,データベースに保存する形にしておいた.

5. クライアントライブラリの選択

クライアントライブラリはAPIの実装を簡単にする,パッケージみたいなものだと思う.

Client Libraries  |  YouTube Data API  |  Google Developers

ここをみるとGoogle API ClientLibrary for go なるものがあったから,これを使うのだろう.

github.com

使ってみて理解が進んだらまた記事にしようかな.

6. Jsonをしっかり理解

完全に理解した.

APIを叩いてみる.

とりあえず今回は,curl で叩く.

Access Token を使ってYouTubeのチャンネル情報を取得してみる.

$curl -H "Authorization: Bearer Access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet\&mine=true

Access_tokenのところにAccess tokenを入れればよい.

得られた結果は次の通り(自分のチャンネルの情報).

{
  "kind": "youtube#channelListResponse",
  "etag": "d1bn9VpVzc_sJex25DypsDa7vYI",
  "pageInfo": {
    "totalResults": 1,
    "resultsPerPage": 1
  },
  "items": [
    {
      "kind": "youtube#channel",
      "etag": "qcyx0gNQud0DuE68vPz_b5ljXZ0",
      "id": "UCOiNaZYE2x6LVisRObnbwMQ",
      "snippet": {
        "title": "絵又-enomata",
        "description": "お絵かき練習の記録を残すために,お絵描き練習ライブや練習動画の投稿をしています.",
        "publishedAt": "2020-05-07T11:37:27Z",
        "thumbnails": {
          "default": {
            "url": "https://yt3.ggpht.com/a/AATXAJyZ3e7eyylr8gkXlKk4tihkVYwxY8G7FTlByg=s88-c-k-c0xffffffff-no-rj-mo",
            "width": 88,
            "height": 88
          },
          "medium": {
            "url": "https://yt3.ggpht.com/a/AATXAJyZ3e7eyylr8gkXlKk4tihkVYwxY8G7FTlByg=s240-c-k-c0xffffffff-no-rj-mo",
            "width": 240,
            "height": 240
          },
          "high": {
            "url": "https://yt3.ggpht.com/a/AATXAJyZ3e7eyylr8gkXlKk4tihkVYwxY8G7FTlByg=s800-c-k-c0xffffffff-no-rj-mo",
            "width": 800,
            "height": 800
          }
        },
        "localized": {
          "title": "絵又-enomata",
          "description": "お絵かき練習の記録を残すために,お絵描き練習ライブや練習動画の投稿をしています."
        },
        "country": "JP"
      }
    }
  ]
}

チャンネル名やらチャンネル説明やらがJsonで取得できた.

こんな感じのJsonを処理してフロントに持っていけばなんかwebアプリできそう.

夢が広がる.

後述

以前,githubでOAuth2.0認証実装したときはoauth2パッケージを使わなかったが今回は使ってみた.

めっちゃ便利だった.

なんかAPIたたく話よりOAuth2.0実装の話の方が多くなってしまった.

まあ導入だし良いか.

次は "YouTube APIつかってWebアプリ作ってみた" みたいな感じにする.

YouTubeAPIはとても要素が多く,使えるようになるのも大変そうだと思ったが,

使いどころもたくさんあるだろうから,楽しく覚えていこうと思う.