Spotify Web APIで明るい楽曲のみのプレイリストを作成する

公開:2021/01/03
更新:2021/01/03
6 min読了の目安(約5900字TECH技術記事

概要

みなさんSpotify使ってますか?
Spotifyの楽曲データにはその曲にどんな特徴があるのかといった情報が含まれています。
この記事ではお気に入り登録した楽曲の中から明るい(Major)と判断されたもののみのプレイリストを作成してみようと思います。
APIの使用にはpythonライブラリであるspotipyを使います。

アクセス認証

まずはアクセス認証をします。クライアントIDなどの取得はこちらから行うことができます。

import spotipy
import spotipy.util as util

username = 'ユーザ名'
client_id = 'クライアントID'
client_secret = 'クライアントシークレット'
redirect_uri = 'http://example.com'

#アプリの権限付与に使用する
#https://developer.spotify.com/documentation/general/guides/scopes/
scope = 'user-library-read user-read-playback-state playlist-read-private user-read-recently-played playlist-read-collaborative playlist-modify-public playlist-modify-private'

token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
sp = spotipy.Spotify(auth = token)

楽曲のIDと曲名を取得

お気に入り登録した楽曲はcurrent_user_saved_tracksで取得することができます。

import pandas as pd

def track_info(limit = 20):
    saved_tracks = sp.current_user_saved_tracks(limit = limit)

    track_id = lambda i: saved_tracks['items'][i]['track']['id']
    track_name = lambda i: sp.track(track_id(i))['name']

    info = [[track_id(i), track_name(i)] for i in range(limit)]
    return pd.DataFrame(info, columns = ['track_id','track_name'])

print(track_info())

                 track_id                        track_name
0   3xkGcE52Hpr8zd34ws2D0A                     hot chocolate
1   5Hqh7J6Oy0Uz85DSx5JUsw                           ストロボナイツ
2   6yK4KPKZa0xX0h58bY96VY                             Miree
3   753nzL4g1fBQt3RuHVHVDQ                 You're Everything
4   0albLGvYx6ftOUJ7KF0i5I                         STAY TUNE
5   0oCP1Vu9LGVP88atKzOswC                         ambiguous
6   0cSkn2l67csUljEy0EEBPn                                 炎
7   3BSPKTravgBDjmuG1rIXvw                     BLOODY STREAM
8   2iOvMtA1u9s95NF6mJDOuT                                香水
9   0E5pNzt2pwd3bOqQsOnfQv  Tick Tock Skip Drop - Mili remix
...

うまく取れてそうですね!(オタク選曲感

楽曲の特徴を取得

特徴はaudio_featuresから取得することができます。
明るい曲が1、暗い曲が0としてカラムのmodeに出力されます。
Get Audio Features for a Track

def track_features(track_ids, limit = 20):
    return pd.DataFrame(sp.audio_features(track_ids))

print(track_features(track_info()['track_id']).drop(['track_href', 'analysis_url', 'id', 'uri'], axis=1))
    danceability  energy  key  loudness  mode  speechiness  acousticness  instrumentalness  liveness  valence    tempo            type  duration_ms  time_signature
0          0.563   0.958    1    -4.514     1       0.0476      0.173000          0.003240    0.2250    0.620  160.421  audio_features       193508               4
1          0.550   0.879    0    -4.496     1       0.0490      0.000826          0.000059    0.1540    0.143  124.989  audio_features       345171               4
2          0.717   0.688   10    -5.886     0       0.0270      0.022500          0.000000    0.1070    0.715  124.015  audio_features       242600               4
3          0.614   0.443    8   -12.060     0       0.0335      0.354000          0.004890    0.1070    0.291   98.974  audio_features       227762               4
4          0.681   0.938    5    -4.246     1       0.0557      0.028800          0.000264    0.0634    0.600  122.991  audio_features       297333               4
5          0.441   0.962    0    -2.299     1       0.1080      0.142000          0.000103    0.3170    0.592  178.201  audio_features       272480               4
6          0.477   0.685    2    -4.554     1       0.0325      0.105000          0.000000    0.2770    0.308  152.040  audio_features       275000               4
7          0.274   0.903    8    -3.125     1       0.0640      0.008600          0.000000    0.3150    0.662  129.999  audio_features       261920               4
8          0.848   0.352    3    -6.838     1       0.0410      0.824000          0.000000    0.0906    0.776  121.833  audio_features       252594               4
9          0.453   0.466    7    -9.435     1       0.0310      0.538000          0.000010    0.0663    0.312   79.987  audio_features       308962               4
...

明るい楽曲のみ取得

先ほどの楽曲名、IDのテーブルと特徴のテーブルを結合し条件を絞ります。

def get_track_from_mode(mode = 1):
    info_with_features = pd.concat([track_info(), track_features(track_info()['track_id'])], axis = 1)
    return info_with_features[info_with_features['mode'] == mode]

print(get_track_from_mode()[['track_id', 'track_name', 'mode']])
                  track_id                        track_name  mode
0   3xkGcE52Hpr8zd34ws2D0A                     hot chocolate     1
1   5Hqh7J6Oy0Uz85DSx5JUsw                           ストロボナイツ     1
4   0albLGvYx6ftOUJ7KF0i5I                         STAY TUNE     1
5   0oCP1Vu9LGVP88atKzOswC                         ambiguous     1
6   0cSkn2l67csUljEy0EEBPn                                 炎     1
7   3BSPKTravgBDjmuG1rIXvw                     BLOODY STREAM     1
8   2iOvMtA1u9s95NF6mJDOuT                                香水     1
9   0E5pNzt2pwd3bOqQsOnfQv  Tick Tock Skip Drop - Mili remix     1
10  3xf3Ji3kDHH62sYK662mwS                              赤の同盟     1
12  5QWtG4MLn5yRVRv0OVPjCl                      Main Heroine     1
...

modeが1の楽曲のみ取得できました。

プレイリストを作成

最後にプレイリストを作成します。

from nested_lookup import nested_lookup

def make_playlist(playlist_name):
    user_id = sp.current_user()['id']

    if playlist_name not in nested_lookup('name', sp.current_user_playlists()):
        sp.user_playlist_create(user_id, playlist_name)
        sp.user_playlist_add_tracks(user = user_id, playlist_id = sp.current_user_playlists()['items'][0]['id'], tracks = get_track_from_mode()['track_id'])

make_playlist('test')


できました!