【初投稿】好きなYoutubeチャンネルの最新動画サムネイルをPCに保存する(Ruby + YouTubeAPI + Docker)

## ■ はじめに
最近YouTubeAPIを使用したアプリを作成したので、復習もかねてRubyでスクリプトを作成しました。
YouTubeAPIやDockerについて深い説明は行いません。参考にした記事のみ貼り付けています。

## ■ 前提
Dockerインストールだけで良いはず...

## ■ ながれ
1.開発環境の構築
2.APIキーを使用してRubyからリクエストする
3.好きなYoutubeチャンネルの情報を取得する
4.投稿動画情報を取得して、サムネイルを抜き出す
5.画像を保存する

## ■1.開発環境の構築
DockerでRubyが実行できる状態 + gemが使える状態まで持っていきます。
以下の記事を元に環境を作ります。

https://zenn.dev/tkakmtst/articles/3ef8913fe3ac5c

```hello_ruby:hello_ruby
　├ vendor
  　└ 色々
　├ app.rb
　├ docker-compose.yml
　├ Dockerfile
　└ Gemfile
```
こういうのができました。
これで十分なので、一度 app.rb が実行できるか確認します。

**■ dockerコンテナへ**
```
hello_ruby$ docker-compose run app sh
```

**■ コンテナ内部でRuby実行**
```
# ruby app.rb
```

**■ 出力結果**
```
Hello Ruby
```
無事出力できましたので、これで開発環境の構築は終了です。

## ■2.APIキーを使用してRubyからリクエストする
次にYoutubeAPIキーを元に、Youtubeへリクエストを飛ばし、レスポンスを受け取ります。
まず、自分のYoutubeAPIキーを取得します。

https://qiita.com/shinkai_/items/10a400c25de270cb02e4

:::note alert
取得したAPIkeyは外部に公開しないこと。
認証情報で制限をかけること。
:::

APIキーを取得できたら、今度はRuby側でYoutubeAPIを使用する準備をします。
「google-api-client」を使用します。

:::note warn
「google-api-clientは非推奨であり、今後更新されることはないでしょう。」
だそうです。大事なアプリで使うのはやめておいた方が良いかもしれません。
:::

**■ Gemfileに「google-api-client」を追加**
```ruby:Gemfile
# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

# gem "rails"
gem 'google-api-client'

```
**■ コンテナ内で bundle install**
```
# bundle install
```
Gemfile.lockファイルが追加され、問題なくインストールできたことを確認したらapp.rbを以下のように変更し、再度実行してみます。
```ruby:app.rb
require 'google/apis/youtube_v3'
youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = "ここに取得したAPIキー"
pp youtube
```
**■ 実行**
```
bundle exec ruby app.rb
```
**■ 出力結果**
```
#<Google::Apis::YoutubeV3::YouTubeService:...以下略>
```
いろいろな情報が確認できたらAPIキーを利用したリクエスト成功です。
## ■3.好きなYoutubeチャンネルの情報を取得する
正しくgemの動作を確認できたら、好きなチャンネルの情報を取得してみます。

:::note warn
ここからYoutubeAPIkeyを使用して、実際にリクエストを飛ばします。
リクエスト数には制限があり、1プロジェクト・ 1日 10,000ユニットまで利用可能です。(2023/04/10現在)
今から実行するリクエストは基本1回1ユニット使用のものですが、リクエスト内容によってユニット数が大きいものもあります。（検索など）
ユニットが枯渇した場合は、1日リクエストが飛ばせなくなるので注意してください。
https://developers.google.com/youtube/v3/getting-started?hl=ja
:::

app.rbを以下のように変更し、実行してみます。
「ここに好きなチャンネルのID」に、自分の好きなチャンネルIDを入力して実際に情報を取得してみます。

https://ilr.jp/tech/485/
```ruby:app.rb
require 'google/apis/youtube_v3'
youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = "ここに取得したAPIキー"
channel_lists = youtube.list_channels('contentDetails', id: "ここに好きなチャンネルのID")
pp channel_lists.items[0].content_details.related_playlists.uploads
```
**■ 実行**
```
bundle exec ruby app.rb
```
**■ 出力結果**
```
"UUPVpbXIiIDwDKVvu68-Vb-A"
```
ここで出力された文字列は「好きなチャンネルのアップロード済み動画の再生リストID」となります。
この再生リストIDを使用して、各動画の情報を取得します。

## ■ 4.投稿動画情報を取得して、サムネイルを抜き出す
app.rbを以下のように変更し、実行してみます。
```ruby:app.rb
require 'google/apis/youtube_v3'
youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = "ここに取得したAPIキー"
channel_lists = youtube.list_channels('contentDetails', id: "ここに好きなチャンネルのID")
uploads = channel_lists.items[0].content_details.related_playlists.uploads
videos = youtube.list_playlist_items('snippet', playlist_id: uploads, max_results: 10)
videos.items.each do |video|
  pp video.snippet.thumbnails.maxres.url
end
```
**■ 出力結果**
```
"https://i.ytimg.com/vi/GKnQgEQOPzk/maxresdefault.jpg"
"https://i.ytimg.com/vi/EgCY7_OUa4E/maxresdefault.jpg"
"https://i.ytimg.com/vi/1lXQUNMIfY8/maxresdefault.jpg"
"https://i.ytimg.com/vi/HIayjW0wbVo/maxresdefault.jpg"
"https://i.ytimg.com/vi/jFILtew61jo/maxresdefault.jpg"
"https://i.ytimg.com/vi/51r6Ptp3t6A/maxresdefault.jpg"
"https://i.ytimg.com/vi/9Ic2oRJNnwE/maxresdefault.jpg"
"https://i.ytimg.com/vi/KfsJmoR_wdk/maxresdefault.jpg"
"https://i.ytimg.com/vi/OaCpkSC_nBQ/maxresdefault.jpg"
"https://i.ytimg.com/vi/mPjzZN7YrbQ/maxresdefault.jpg"
```
何をしているかと言うと、取得した再生リストIDのアップロード動画を取得して、その動画リストのサムネイル(URL)を、ひとつひとつ出力しています。
URLが取得できれば、Rubyではopen-uriが使用できるので、あとは保存するだけです。
## ■ 5.画像を保存する
あとはopen-uriにて画像を保存します。
今回はdockerにて「WORKDIR /app」しているので、app直下にimageというフォルダを作成してしてみます。
```ruby:app.rb
require 'google/apis/youtube_v3'

youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = "ここに取得したAPIキー"
channel_lists = youtube.list_channels('contentDetails', id: "ここに好きなチャンネルのID")
uploads = channel_lists.items[0].content_details.related_playlists.uploads
videos = youtube.list_playlist_items('snippet', playlist_id: uploads, max_results: 10)

url_array = []
videos.items.each do |video|
  url_array << video.snippet.thumbnails.maxres.url
end

require 'open-uri'
url_array.each_with_index do |url, i|
  file_name = "#{i}.png"
  dir_name = "/app/image/"
  file_path = dir_name + file_name
  FileUtils.mkdir_p(dir_name) unless FileTest.exist?(dir_name)
  URI.open(file_path, 'wb') do |pass|
    URI.open(url) do |recieve|
      pass.write(recieve.read)
    end
  end
end
```
**■ 実行**
```
bundle exec ruby app.rb
```
**■ 出力結果**
```hello_ruby:hello_ruby
　├ image
    ├ 0.png
    ├ 1.png
    ├ 2.png
    ├ 3.png
    ├ 4.png
    ├ 5.png
    ├ 6.png
    ├ 7.png
    ├ 8.png
    └ 9.png
　├ vendor
  　└ 色々
　├ app.rb
　├ docker-compose.yml
　├ Dockerfile
　└ Gemfile
```
![スクリーンショット 2023-04-11 22.34.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387747/b2586b50-cc73-56ce-7f7a-d86d28b6b66a.png)
画像が保存できたことを確認できました。
## ■完成品
https://github.com/koo-ke/get_thumbnail
## ■まとめ
最近利用したYouTubeAPIと、適当に作ったら結構会社で役立っている画像保存スクリプトを合わせて作成しました。
YouTubeAPIには色々制限があり、なんでも作れるだろーと息巻いてアプリを作成したら痛い目をみたので、みなさんも使用する際は気をつけてください。

あと初投稿で慣れておらず、記事に問題がありましたら連絡ください...