跳到主要內容

[Python實戰應用]瞭解Python存取API的重要觀念-以KKBOX Open API為例

Photo by Nirmal Rajendharkumar on Unsplash
在現今很多網站,都會透過API(Application Programming Interface)的方式來提供服務,讓用呼端能夠藉由這個介面存取其資料,進行多樣化的應用開發。本文就以KKBOX Open API為例,實作一個簡單的專案,示範Python如何存取音樂排行榜API,並且可以讓使用者選擇想聽的排行榜類別,試聽其中的歌曲。

經過本文的教學,將會瞭解API的基本觀念,以及學會如何解析Python存取API後的回傳結果,並且篩選所需的欄位,重點包含了:
  • 什麼是API
  • 專案前置準備
  • KKBOX Open API
  • 用戶端憑證(Client Credentials)
  • KKBOX Open API - Charts

一、什麼是API

各位可以將API(Application Programming Interface)想像是一個大門,要進入存取必須提供合法的帳號及密碼,才能拿到存取憑證(Access Token)之後要存取門後的API資源,只要帶著這個憑證,就可以進行存取。

而實際上API就是一組網址,透過HTTP協定來和用戶端進行溝通。舉例來說,各位可以開啟Chrome瀏覽器,按下F12進入開發者視窗,點擊Network頁籤,接著輸入google.com.tw網址,可以看到類似下圖的結果:
點選任一個網址,可以看到以下的資訊:
其中的Headers(標頭)就是瀏覽器發送至Google的資訊,如果換成是存取KKBOX Open APIRequest URL就是API網址,Request Method有幾個常用的類型,分別有:
  • GET(查詢資料)
  • POST(新增資料)
  • PUT(修改資料)
  • DELETE(刪除資料)
以上四個是在存取API時,常用的HTTP動詞。而Response頁籤中的內容即是Google回傳給瀏覽器的結果。

二、專案前置準備

有了基本的API觀念後接著建立一個專案,並且開啟Python開發工具,本文將以Visual Studio Code來進行教學。透過 pipenv 套件管理工具來為專案建立虛擬環境及安裝requests套件(Package),如下範例:
接下來,利用pipenv shell指令進入虛擬環境後,在專案中新增charts.py檔,完成即可進行今天KKBOX Open APIPython實作練習囉。

三、KKBOX Open API

KKBOX Open API為KKBOX平台所提供的開放API,透過此API即可取得歌曲、排行榜、熱門歌單等音樂資訊,並且有提供幾個程式語言的軟體開發套件(SDK, Software Development Kit),提升開發專案的效率,而本文為讓各位瞭解背後執行的原理,所以利用原始的存取方式來進行教學。

在進行開發前,前往KKBOX Open API文件首頁,如下圖:

點擊上方的My Apps來建立一個App,如下圖:
接著註冊KKBOX帳號,並且登入後,就可以進行建立App的動作了,如下圖
第一次建立App會看到此畫面,接著點擊Create new app,輸入App名稱及簡單描述,如下範例:
送出資料後,就會得到一組屬於這個App的ID(帳號)及Secret(密碼),如下範例:
這組ID(帳號)及Secret(密碼)將會是接下來存取KKBOX Open API時,用來取得憑證的依據。

四、用戶端憑證(Client Credentials)

App建立完成後,點擊上方API Reference(API參考文件),左側可以看到所有的KKBOX Open API,如下範例:
要存取API前,必須提供剛剛建立App時所拿到的ID(帳號)及Secret(密碼),才能取得KKBOX用戶端憑證(Client Credentials 或 Access Token),並且在所有的API呼叫中,都要帶著,讓KKBOX知道您是通過驗證的用戶端或專案,才會允許您的呼叫動作。

那要如何取得憑證呢?在API Reference的Client Credentials Flow中,說明了取得憑證的API網址、標頭(Header)及參數資訊,如下:

開啟 charts.py ,建立一個名稱為 get_access_token()的函式(Function) ,如下範例:

import requests


# 取得Token
def get_access_token():
    #API網址    
    url = "https://account.kkbox.com/oauth2/token" 
    
    #標頭
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "Host": "account.kkbox.com"
    }

    #參數
    data = {
        "grant_type": "client_credentials",
        "client_id": "貼上ID內容",
        "client_secret": "貼上Secret內容"
    }

    access_token = requests.post(url, headers=headers, data=data)
    return access_token.json()["access_token"]
由於需要發出request請求,所以引用requests套件(Package),並且根據API Reference(API參考文件),分別指派API網址、標頭(Header)及參數(data)資訊,接著透過requests套件(Package)的post方法取得結果,最後利用json()方法將結果轉換為字典(Dictionary),再使用 [] 符號讀取憑證欄位資料。

五、KKBOX Open API - Charts

有了存取憑證(Access Token)後,就可以進行KKBOX Open API的呼叫了,接下來將以Charts API為例,取得KKBOX音樂排行榜的資料。

首先,要取得各種音樂排行榜的清單,可以透過 /charts API網址來取得,而API Reference(API參考文件)說明如下:



在charts.py中,新增一個名稱為 get_charts()的函式(Function) ,如下範例:
# 取得各種音樂排行榜列表
def get_charts():
    #取得存取憑證
    access_token = get_access_token() 

   #取得音樂排行榜列表API網址
    url = "https://api.kkbox.com/v1.1/charts"

    #標頭
    headers = {
        "accept": "application/json",
        "authorization": "Bearer " + access_token  #帶著存取憑證
    }

    #參數
    params = {
        "territory": "TW"  #台灣領域  
    }

    response = requests.get(url, headers=headers, params=params)
    result = response.json()["data"]
    for item in result:
        print(item["id"], item["title"])


get_charts()
回傳結果範例
{
  "data": [
    {
      "id": "LZPhK2EyYzN15dU-PT",
      "title": "綜合新歌即時榜",
      "description": "綜合新歌即時榜",
      "url": "https://www.kkbox.com/tw/tc/playlist/LZPhK2EyYzN15dU-PT",
      "images": [
        {
          "height": 300,
          "width": 300,
          "url": "https://i.kfs.io/playlist/global/59599602v1259/cropresize/300x300.jpg"
        },
        {
          "height": 600,
          "width": 600,
          "url": "https://i.kfs.io/playlist/global/59599602v1259/cropresize/600x600.jpg"
        },
        {
          "height": 1000,
          "width": 1000,
          "url": "https://i.kfs.io/playlist/global/59599602v1259/cropresize/1000x1000.jpg"
        }
      ],
      "updated_at": "2019-08-02T03:01:58+00:00",
      "owner": {
        "id": "T-YMdq3gnf6AVbuqgt",
        "url": "https://www.kkbox.com/tw/profile/T-YMdq3gnf6AVbuqgt",
        "name": "KKBOX",
        "description": "",
        "images": [
          {
            "height": 75,
            "width": 75,
            "url": "https://i.kfs.io/muser/global/noimg/cropresize/75x75.jpg"
          },
          {
            "height": 180,
            "width": 180,
            "url": "https://i.kfs.io/muser/global/noimg/cropresize/180x180.jpg"
          },
          {
            "height": 300,
            "width": 300,
            "url": "https://i.kfs.io/muser/global/noimg/cropresize/300x300.jpg"
          }
        ]
      }
    },
 ...
  ],
  "paging": {
    "offset": 0,
    "limit": 5,
    "previous": null,
    "next": null
  },
  "summary": {
    "total": 29
  }
}
前面有提到,要呼叫任何的KKBOX Open API時,標頭(Header)都要帶有存取憑證(Access Token),所以在12行的標頭(headers) authorization 欄位,要加上存取憑證(Access Token)。而 territory 參數需指定API參考文件中的代碼。

由於要執行查詢的動作,所以透過requests套件(Package)的get()方法來進行API呼叫。從API文件提供的回傳結果範例可以看到,利用json()方法轉為字典(Dictionary)後,可以透過 [] 符號存取data欄位資料,也就是串列(List),接著就可以利用for迴圈進行讀取,最後取得id(列表ID)及title(列表名稱),執行結果如下:

要取得各個排行榜中的歌曲,就要呼叫另一個 /charts/:chart_id/tracks API網址,並且傳入此列表ID,API文件說明如下:


在charts.py中,新增一個名稱為get_charts_tracks(chart_id)的函式(Function),如下範例:

# 取得該音樂排行榜的歌曲列表
def get_charts_tracks(chart_id):
    #存取憑證
    access_token = get_access_token() 

    #取得音樂排行榜列表中的歌曲API網址
    url = "https://api.kkbox.com/v1.1/charts/" + chart_id + "/tracks"

    #標頭
    headers = {
        "accept": "application/json",
        "authorization": "Bearer " + access_token
    }

    #參數
    params = {
        "territory": "TW"  #台灣領域
    }

    response = requests.get(url, headers=headers, params=params)
    result = response.json()["data"]
    for item in result:
        print([item["name"], item["url"]])


get_charts()
print("===========================================")

try:
    chart_id = input("請貼上想聽的音樂排行榜ID: ")
    get_charts_tracks(chart_id)
except KeyError:
    print("請貼上正確的音樂排行榜ID")
回傳結果範例
{
  "data": [
    {
      "id": "Cl6IBBqIFKtg2hkWuB",
      "name": "有一種悲傷 (A Kind of Sorrow)",
      "duration": 237008,
      "url": "https://www.kkbox.com/tw/tc/song/EJT009KS-TZFBgeRFBgeR0XL-index.html",
      "track_number": 1,
      "explicitness": false,
      "available_territories": [
        "TW",
        "HK",
        "SG",
        "MY",
        "JP"
      ],
      "album": {
        "id": "OtS1j6YhEqbM8XuF5D",
        "name": "有一種悲傷 (A Kind of Sorrow)",
        "url": "https://www.kkbox.com/tw/tc/album/aMZ0PysNRqgHN0F2RKf6009H-index.html",
        "explicitness": false,
        "available_territories": [
          "TW",
          "HK",
          "SG",
          "MY",
          "JP"
        ],
        "release_date": "2018-10-12",
        "images": [
          {
            "height": 160,
            "width": 160,
            "url": "https://i.kfs.io/album/global/40716998,1v1/fit/160x160.jpg"
          },
          {
            "height": 500,
            "width": 500,
            "url": "https://i.kfs.io/album/global/40716998,1v1/fit/500x500.jpg"
          },
          {
            "height": 1000,
            "width": 1000,
            "url": "https://i.kfs.io/album/global/40716998,1v1/fit/1000x1000.jpg"
          }
        ],
        "artist": {
          "id": "Osbh3TUzyafhBl0WD5",
          "name": "A-Lin",
          "url": "https://www.kkbox.com/tw/tc/artist/RTQrEhYKUkU5NCX0F03LZ08J-index-1.html",
          "images": [
            {
              "height": 160,
              "width": 160,
              "url": "https://i.kfs.io/artist/global/13667,0v22/fit/160x160.jpg"
            },
            {
              "height": 300,
              "width": 300,
              "url": "https://i.kfs.io/artist/global/13667,0v22/fit/300x300.jpg"
            }
          ]
        }
      }
    },
 ...
  ],
  "paging": {
    "offset": 0,
    "limit": 2,
    "previous": null,
    "next": "https://api.kkbox.com/v1.1/charts/X-6lSz-IwzDxkPuDP-/tracks?limit=2&territory=TW&offset=2"
  },
  "summary": {
    "total": 100
  }
}
除了需在標頭(headers)authorization加上存取憑證(Access Token)外,在第8行的API網址需加上列表ID,而參數的部分這邊僅傳入台灣領域。

API同樣為查詢動作,所以透過requests套件(Package)get()方法進行呼叫,將回傳結果利用json()方法轉為字典(Dictionary)後,使用 [] 符號存取data欄位中的資料,最後利用for迴圈讀取name(歌曲名稱)及url(歌曲試聽網址),為了輸出結果的可讀性,所以將此兩個欄位資料轉型為串列(List)。

由於和使用者有互動的效果,所以利用input()函式取得使用者貼上的列表ID,為了防止隨意輸入產生錯誤,使用Python例外處理機制,顯示警告訊息,如果無誤則將列表ID傳入get_charts_tracks(chart_id)函式,來取得列表中的歌曲,執行結果如下:
接下來,就可以按著Ctrl鍵不放,點擊後面的連結,開啟網頁版KKBOX來進行試聽囉~

六、小結

以上就是利用Python存取KKBOX Open API的簡單應用,各位藉此瞭解Python呼叫API的方式及回傳結果的解析後,可以試著練習其他的API,如果在練習的過程中有碰到任何問題,歡迎留言分享。

如果您喜歡我的文章,請幫我按五下Like(使用GoogleFacebook帳號免費註冊),支持我創作教學文章,回饋由LikeCoin基金會出資,完全不會花到錢,感謝大家。

有想要看的教學內容嗎?歡迎利用以下的Google表單讓我知道,將有機會成為教學文章,分享給大家😊

你可能有興趣的文章









留言

張貼留言