[教學] 以 YouTube Data API 擷取 YouTube 影片資訊 [Ruby on Rails]

YouTube社交媒體精選教學網頁界面設計網頁製作

Google 各種服務都提供 API 供人方便存取資料,YouTube 當然不例外,讓大家以 Data API 讀取 YouTube 的頻道和影片資料。今次教學就使用較為冷門的 Ruby on Rails 來使用 Data API 以關鍵字搜尋影片。

在這裡會提及:

  1. YouTube Data API 簡介
  2. Rails Service Object
  3. Rails Cache (快取)

有關如何在 Google Developers Console 設立 Project 並獲得 API Key,可自行參考其他網站,或到 YouTube 開發者網站查詢。另外,由於以 API 搜尋影片毋須使用用戶資料,故不涉及 OAuth。

YouTube Data API 簡介

YouTube Data API v3

透過 YouTube Data API,開發者可以存取 YouTube 上不同資源,包括影片( video )、頻道( channel )、播放清單( playlist )等,並可執行讀取( list )、加入( insert )、刪除( delete )、更新( update )的動作。部分動作需要得到用戶權限才可,故需使用 OAuth,不過在這次範例中並不包括。請瀏覽 API 的官方網站了解更多。

1. 必要的參數:part

我們會透過各種參數(parameters)來存取想要的資源,像是頻道 ID、影片 ID、關鍵字等等,但每個 YouTube API 請求都必須要有 part 參數,目的是限制回傳的 json 資料類型,以減少不必要的資料和伺服器負擔。

以 Channel 資源為例,以下是可回傳的 json 資料:

{
  "kind": "youtube#channel",
  "etag": etag,
  "id": string,
  "snippet": {
    "title": string,
    "description": string,
    "customUrl": string,
    "publishedAt": datetime,
    "thumbnails": {
      (key): {
        "url": string,
        "width": unsigned integer,
        "height": unsigned integer
      }
    },
    "defaultLanguage": string,
    "localized": {
      "title": string,
      "description": string
    },
    "country": string
  },
  "contentDetails": {
    "relatedPlaylists": {
      "likes": string,
      "favorites": string,
      "uploads": string,
      "watchHistory": string,
      "watchLater": string
    }
  },
  "statistics": {
    "viewCount": unsigned long,
    "commentCount": unsigned long,
    "subscriberCount": unsigned long,  // this value is rounded to three significant figures
    "hiddenSubscriberCount": boolean,
    "videoCount": unsigned long
  },
  略...
  }
}

從中可見,一個 Channel 可以回傳多項資料,但並非所有資料都會被使用,所以我們須使用 part 參數來限制。part 參數的值包括 snippet、contentDetails 等,說穿了就是 json 檔的主鍵(key)。如果只設定了 part=snippet,那回傳的 json 就只會有 snippet 的內容。

2. API 配額限制

YouTube Data API v3 配額

YouTube Data API 每日有 10,000 個單位配額,每執行一個 API 請求均會消耗配額,其中每次 Search 會消耗 100 單位,故為 API 快取是非常重要。

3. Rails gem:Google Client Library

在 Rails 使用 Google 的 API 需要 google-api-client gem。於 gemfile 加入 gem 'google-api-client', '~> 0.34',然後 bundle install

必須要注意!在 YouTube 開發者網站的樣本 Ruby 程式碼似乎是錯誤的,因為現在使用的都是 require 'google/apis/***' 而非 require 'google/api_client'

詳細請見 Github。(Migrating from version 0.8.x to 0.9 or above)

Rails 程式碼範例

了解 YouTube Data API 後,是時候動手寫 Rails 程式碼。我們會使用 Service Object,以讓我們在 Controller 以 new 建立物件,最後在 View 中使用。

  class YoutubeService
      
  require 'google/apis/youtube_v3'
  Google::Apis::RequestOptions.default.retries = 3
  
  
  $service = Google::Apis::YoutubeV3::YouTubeService.new  
  $service.key = "APIKEY"

  def initialize()
  end

  def show_videos_items(service, part, **params)
    response = service.list_searches(part, params).to_json
    items = JSON.parse(response).fetch("items")
    return items
  end

  def show_videos(query)
    Rails.cache.fetch("videos", expires_in: 12.hours)do 
      show_videos_items($service, 'snippet', {q: query, type: "video"})
    end
  end
end
@videos =  YoutubeService.new
<% @videos.show_videos("replace with your query").each do |video| %>
    <%= link_to "https://youtube.com/watch?v=#{video.fetch("id").fetch("videoId")}" do %>
       <%= image_tag  "#{video.fetch("snippet").fetch("thumbnails").fetch("medium").fetch("url")}" %>
    <% end %>
<% end %>

程式碼解說:

  • class YoutubeService 讓我們在 Controller 以 YoutubeService.new 建立物件
  • require 'google/apis/youtube_v3' 採用 Google Client Library
  • def initialize() 必須使用以在 new 傳入參數,不過在這裡其實並無必要
  • $service = Google::Apis::YoutubeV3::YouTubeService.new 建立 API 物件,以使用 YouTube Data API 提供的方法
  • def show_videos_items(service, part, **params) 引入 $service 物件以使用 YouTube Data API 的方法;引入必要參數 part;引入自選參數 params 存取指定資源
  • Search 的 part 參數只能是 Snippet
  • def show_videos(query) 方法讓以 new 建立的物件,可在 view 傳送搜尋字眼來使用

成功的話,理應可在 Terminal 看到 Rails 發出 GET 請求,並回傳 json 檔。YouTube Data API 網站亦提供其他資源的存取方法,開發者可加入更多參數(如 max_result, order 等) 調整搜尋結果,亦可將 list_searches 換成其他方法,以尋找頻道、留言等資訊。(params 與以上範例程式碼稍有不同。)

在 Ruby on Rails 的 Terminal 可見 YouTube Data API 發送的請求

效果 (view 與以上樣本程式碼稍有不同)

將 YouTube Data API 回傳的 json 檔在 view 中處理

為 API 回傳建立快取

正如以上所講,每次的 Search 均會消耗 100 單位配額,所以我們必須建立快取。使用Rails.cache.fetch 方法正正可為 show_videos_items 回傳的 json 建立快取,而 expires_in 便可設定快取過期時間。

另外,在 Rails 的 Development mode 預設不會開啟快取模式,故必須執行 rails dev:cache 以啟用快取。

成功的話,重新整理網頁時 Rails 不會再次發出 API 請求。

參考資料

YouTube Data API | Google Developers

Github:google-api-ruby-client

Rails 程式碼整理術(進階)(Service Object)

Caching with Rails: An Overview

Caching in development environment in Rails 5