0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Go]GAEとローカルでYoutubeDataAPIを使用する

Posted at

はじめに

YoutubeDataAPIを使用するとYoutubeのチャンネルやアップロードされた動画の情報を取得することができます。
今回はYoutubeDataAPIをGAEとローカル環境で使用する方法について記載します。
使用する言語はgoです。
YoutubeDataAPIを使用する際に認証方法としてよくAPIキーによる方法が使用されていますが、GAEで使用する場合はGAEデフォルトのサービスアカウントを使用することもできます
この記事では認証にサービスアカウントを使用します。

プロジェクト準備

適当なGCPプロジェクトを作成し、GAEにアプリケーションをデプロイします。
アプリケーションをデプロイすることでデフォルトのサービスアカウントが作成されるので内容は何でもいいのでデプロイしてください。

デプロイすると IAMと管理 > サービスアカウントApp Engine default service accountという名前のサービスアカウントが作成されています。
このアカウントのキーを作成し、キーのタイプはJSONで保存してください。

image.png

このキーはローカルでYoutubeDataAPIを使用する際に必要になります。

次にGCPコンソールの上部の検索ウィンドウからYoutubeと検索し、でてきたYoutube Data API v3を有効化します。

これでプロジェクトの準備は完了です。

YoutubeDataAPIを使用する

以下のコマンドで必要ライブラリをインストールします。

$ go get golang.org/x/oauth2/google
$ go get google.golang.org/api/youtube/v3

ローカルで使用する場合は環境変数GOOGLE_APPLICATION_CREDENTIALSにプロジェクト準備で取得したサービスアカウントのキーへのパスを設定します。
GAEで使用する場合は特に何もする必要はありません。

後は以下のコードで使用することができます。
詳細はコメントを参照してください。

main.go
// 特定のチャンネルの動画を5件取得し、そのタイトル、投稿日時、長さを表示する
package main

import (
	"context"
	"log"
	"strings"

	"golang.org/x/oauth2/google"
	"google.golang.org/api/youtube/v3"
)

// video 取得した動画の情報を表す構造体
type video struct {
	id          string
	title       string
	publishedAt string
}

func hoge() {
	ctx := context.Background()
	// サービスアカウントを使用した認証用のhttpクライアントを作成
	// 環境変数`GOOGLE_APPLICATION_CREDENTIALS`が設定されている場合は自動で必要な設定をしてくれる
	client, err := google.DefaultClient(ctx, youtube.YoutubeReadonlyScope)
	if err != nil {
		log.Fatalf("Error creating google client: %v", err)
	}

	// youtubeAPIサービスの作成
	service, err := youtube.New(client)
	if err != nil {
		log.Fatalf("Error creating YouTube client: %v", err)
	}

	// 取得するチャンネルのID
	const channelID = "UCLhUvJ_wO9hOvv_yYENu4fQ"

	channelRes, err := service.Channels.List("contentDetails").Id(channelID).Do()
	if err != nil {
		log.Fatalf("Cannot get channel: %v", err)
	}

	channel := channelRes.Items[0]
	// アップロードされた動画から5件を取得する
	// 並び順は必ずしも公開日順とは限らないがだいたい公開日順に並んでいる
	// (最新の動画が先頭ではない可能性がある。アップロード順という説もあるが詳細不明。)
	// 最大50件まで同時に取得可能
	// 50件より多く取得したい場合はNextPageTokenを使用する
	itemRes, err := service.PlaylistItems.List("snippet").
		PlaylistId(channel.ContentDetails.RelatedPlaylists.Uploads).
		MaxResults(5).
		Do()
	if err != nil {
		log.Fatalf("Cannot get playlistitem: %v", err)
	}

	videos := make([]video, 0, len(itemRes.Items))
	videoIDs := make([]string, 0, len(itemRes.Items))
	for _, it := range itemRes.Items {
		// PlaylistItemsでは動画の長さがわからない
		v := video{
			id:          it.Snippet.ResourceId.VideoId,
			title:       it.Snippet.Title,
			publishedAt: it.Snippet.PublishedAt,
		}
		videos = append(videos, v)
		videoIDs = append(videoIDs, it.Snippet.ResourceId.VideoId)
	}

	// 動画の詳細情報を取得する
	videoIDsStr := strings.Join(videoIDs, ",")
	videoRes, err := service.Videos.List("contentDetails").Id(videoIDsStr).Do()
	durationMap := map[string]string{}
	for _, v := range videoRes.Items {
		durationMap[v.Id] = v.ContentDetails.Duration
	}

	// タイトル、投稿日時、長さを表示する
	for _, v := range videos {
		log.Printf("%v - %v - %v", v.title, v.publishedAt, durationMap[v.id])
	}
}
実行結果
2020/02/02 21:57:46 ポケモン都市伝説 - 2020-02-02T10:00:13.000Z - PT5M34S
2020/02/02 21:57:46 今回はすごく欲求不満になりました…【アプリ実況】 - 2020-02-01T10:00:03.000Z - PT12M24S
2020/02/02 21:57:46 感情を縛られた結果、どうすることもできませんでした。ごめんなさい【#シロ生放送】 - 2020-01-30T12:30:00.000Z - PT1H21M24S
2020/02/02 21:57:46 同じ動画素材を全く違う編集にしてみたらどうなる? - 2020-01-31T10:00:11.000Z - PT5M43S
2020/02/02 21:57:46 絶対に再生を止められない動画 - 2020-01-29T10:00:05.000Z - PT4M19S
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?