🎵

Spotify APIを用いた楽曲名の完全一致検索・プレイリスト自動作成

2024/07/28に公開

概要

Spotify APIを用いて、下記を自動化しました。

  • Spotifyの楽曲で、指定したキーワードと完全一致する楽曲情報を取得する。
  • 取得した楽曲から成るプレイリストを作成する。

これにより、例えば楽曲名が「ありがとう」のプレイリストを自動作成でき、
日本中の様々な「ありがとう」を聴くことできます。

コード一式をGitHub上に公開しております。
https://github.com/TheTwinkleOfTheStars/Search-Spotify-Music/tree/main

きっかけ

Spotify上で曲名を検索すると、検索ワードとの関連度が高いと思われる楽曲が上から並んでおり、
検索ワードと完全一致する楽曲のみを取得する方法が見当たりませんでした。


「夏」の検索結果。検索ワードと完全部分一致しない楽曲も含まれています。

そこで、Spotify Web APIを利用して、検索ワードと完全一致する楽曲の取得 + プレイリストの作成を自動化してみました。

事前準備

  • Spotifyの準備
    • Spotify Developers ユーザーアカウントの作成。
    • appを作成し、クライアントID、クライアントシークレット、ユーザー名の確認。
  • Pythonの環境構築
    • Python3.12のインストール
    • Poetryによる仮想環境の構築
      • 詳細はREADME.md「PoetryによるPythonの環境構築」をご参照ください。

実装方針

2つのタスクに分けて実装していきます。

  • タスク1: 楽曲情報の取得
  • タスク2: プレイリストの作成

タスク1:楽曲情報の取得

インポート

spotipy_utils.py
from typing import Optional

import spotipy
import spotipy.util as util

APIによる楽曲情報の取得

Spotipyを使ってSpotify APIを叩き、楽曲の情報を取得します。
APIの楽曲検索機能には完全一致検索機能は見当たらなかったため、2ステップに分けて実装します。

  1. 指定したキーワードでトラックを検索する。(get_track_info()関数)
  2. 取得したトラックのうち、トラック名がキーワードと完全一致するトラックのIDを抽出する。
    ここで、トラックIDとは、Spotifyの楽曲を一意に識別するためのものです。トラックIDを取得することで楽曲を参照でき、プレイリストを作成することができます。
spotipy_utils.py
def get_track_info(word: str, sp: spotipy.Spotify) -> Optional[list]:
    """指定されたキーワードを使用してSpotifyのトラックを検索し、トラック情報を取得する。

    Args:
        word (str): 検索する楽曲名。
        sp (spotipy.Spotify): 検索を実行するために使用するSpotipyクライアントインスタンス。

    Returns:
        Optional[dict]: 成功した場合はトラック情報の辞書のリスト、失敗した場合はNoneを返す。

    Notes: 
        - Spotipyで一度にリクエストできる曲の上限が50曲であるため、オフセットを利用して50曲ずつ検索結果を取得する。
    """
    tracks = []
    for offset_n in range(0, 1_000, 50):
        try:
            # market="JP": 日本市場で利用可能なコンテンツに限定。
            response = sp.search(q=f'track:{word}', type='track', limit=50, market="JP", offset=offset_n)
            tracks += response["tracks"]["items"]
        except Exception as e:
            print(f"offset:{offset_n} {e}")
    return tracks

spotipy_utils.py
def get_id_by_perfect_matching(word: str, tracks: dict) -> list:
    """指定された単語と完全一致するトラックIDのリストを取得する。

    Args:
        word (str): 検索する楽曲名。
        tracks (dict): トラック情報。get_track_info()により出力された辞書を想定。

    Returns:
        list: wordと完全一致する楽曲のIDのリスト。

    """
    ids = []
    for track in tracks:
        if track.get("name") == word:
            ids.append(track.get("id"))
    return ids

タスク2:プレイリストの作成

抽出したトラックIDを使い、プレイリストを作成します。

spotipy_utils.py
def make_playlist(sp: spotipy.Spotify, username: str, playlist_name: str, ids: list) -> None:
    """指定したユーザ上に、IDリストの楽曲から成るプレイリストを作成する。

    Args:
        sp (spotipy.Spotify): Spotipyクライアントインスタンス。
        username (str): プレイリストを作成するユーザー名。
        playlist_name (str): 新しいプレイリストの名前。
        ids (list): プレイリストに追加するトラックのIDリスト。

    """
    try:
        # 空のプレイリストを作成。
        playlists = sp.user_playlist_create(username, playlist_name)

        # プレイリストに曲を追加。
        # 100曲超のトラックを一度にプレイリストに追加しようとするとエラーが発生するため、
        # チャンクに分割してプレイリストに追加。
        chunk_size = 100
        for i in range(0, len(ids), chunk_size):
            ids_chunk = ids[i:i+chunk_size]
            sp.user_playlist_add_tracks(username, playlists['id'], ids_chunk)
    except Exception as e:
        print(e)

main.pyの実行

一連の処理を1つの関数make_playlist_by_perfect_matching()にまとます。

spotipy_utils.py
def make_playlist_by_perfect_matching(word: dict, authentication_dic: dict):
    """指定したキーワードと完全一致する楽曲名のプレイリストを作成する。

        APIを利用し、引数wordに関連する楽曲最大1,000曲の情報を取得。
        得られた楽曲のうち曲名がwordと完全一致する曲のみからなるプレイリストを作成する。

    Args:
        word (dict): キーワード(楽曲名)。
        authentication_dic (dict): 下記のSpotify認証情報を含む辞書。
            - 'client_id' (str): SpotifyのクライアントID。
            - 'client_secret' (str): Spotifyのクライアントシークレット。
            - 'username' (str): Spotifyのユーザ名。
            - 'redirect_url' (str): SpotifyのリダイレクトURL。
            - 'scope' (str): スコープ。

    Notes:
        - 引数wordの関連楽曲が1,000曲以上存在する場合、検索結果の上位1,000曲のみ
          が抽出対象となる。
    """
    token = util.prompt_for_user_token(**authentication_dic)
    sp = spotipy.Spotify(auth=token)
    # APIを叩き、条件を満たすトラックのIDリストを取得
    tracks = get_track_info(word, sp=sp)
    ids = get_id_by_perfect_matching(word, tracks)
    make_playlist(sp=sp, username=authentication_dic["username"], playlist_name=word, ids=ids)

main.py上では、ユーザー情報(ユーザーネーム、クライアントID、クライアントシークレット、リダイレクトURL)からなる辞書authentication_dicをインポートし、make_playlist_by_perfect_matching()関数を呼び出します。

main.py
""" 指定した文字列と完全一致する楽曲からなるSpotifyのプレイリストを作成する。
"""

from config import authentication_dic
from spotipy_utils import make_playlist_by_perfect_matching

# 検索したい楽曲名を代入する
word = "夏"
make_playlist_by_perfect_matching(word, authentication_dic)

main.pyを実行することで、曲名が「夏」 (重要:「夏の〜〜」など完全一致しない曲を含まない!)である楽曲のプレイリストを作成することができます。

Discussion