概要
内容はタイトルママ
SpotifyAPIとYouTubeMusicAPI使う
YouTubeMusicAPIは非公式なので一応注意
spotifyAPIに関しては資料が多いので省略
この記事がわかりやすいのでおすすめ
YouTubeMusicAPIは資料少ないので下の方で解説する
環境
- Python 3.9.7
- ytmusicapi==1.1.1
- spotipy==2.23.0
処理の流れ
spotifyAPIでいいねした曲を取得したあと、YouTubeMusicAPIで検索して曲名とidを抽出
jsonにspotifyの曲名、ytmusicの検索曲名、ytmusicの検索曲idを保存
json内容を確認してもらい(検索結果が間違ってる可能性があるので)、問題なかったらjsonを元にいいねする関数を起動して終わり
処理順
- spotifyAPI(spotipy)でいいねした曲の、曲名&アーティスト名を取得する
- 取得した曲名&アーティスト名をYouTubeMusicAPI(ytmusicapi)で検索
- 検索結果から曲名とidを抽出し、spotifyでいいねした曲名と一緒にjsonで保存
- json内容に問題なかったら、ytmusicで"いいね"する関数を起動して終わり
コード
import os
import json
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import ytmusicapi
class Spotify2YTMusic():
def __init__(self):
# Spotify APIの設定
SPOTIFY_CLIENT_ID = 'your client id'
SPOTIFY_CLIENT_SECRET = 'your client secret'
SPOTIFY_REDIRECT_URI = 'your redirect uri'
self.sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=SPOTIFY_CLIENT_ID,
client_secret=SPOTIFY_CLIENT_SECRET,
redirect_uri=SPOTIFY_REDIRECT_URI,
scope='user-library-read'))
# YTMusicの設定
# browser.jsonファイルが存在しなかったら作成
if not os.path.exists('browser.json'):
ytmusicapi.setup_oauth(filepath="browser.json")
# 作成したbrowser.jsonファイルで設定
self.ytmusic = ytmusicapi.YTMusic("browser.json")
# combined_data.jsonファイルが存在するかチェック
if os.path.exists('combined_data.json'):
# combined_data.jsonファイルが存在する場合はデータをロードする
with open('combined_data.json', 'r', encoding='utf-8') as f:
self.combined_data = json.load(f)
else:
# combined_data.jsonファイルが存在しない場合は空のリストを作成する
self.combined_data = []
# Spotifyでいいねした曲を取得する関数
def _get_liked_tracks(self):
liked_tracks = []
offset = 0
limit = 50 # 取得する曲の数(50曲ごとにAPIリクエストを送信)
while True:
results = self.sp.current_user_saved_tracks(limit=limit, offset=offset)
for item in results['items']:
track = item['track']
liked_tracks.append({
'name': track['name'],
'artist': track['artists'][0]['name']
})
# 次のページがある場合はオフセットを更新してループを続ける
if results['next']:
offset += limit
else:
break
return liked_tracks
# ytmusicの検索結果を取得する関数
def _search_youtube_music(self,query):
search_results = self.ytmusic.search(query)
for result in search_results:
if result['resultType'] != 'song':
continue
print(result['title'])
print(result['resultType'])
music = {
'title': result['title'],
'id': result['videoId']
}
print(music)
return music
# ytmusicの検索結果をjsonにして出力
def printJSON(self):
liked_tracks = self._get_liked_tracks()
combined_data = []
for track in liked_tracks:
yt_top_result = self._search_youtube_music(track['name'] + ' ' + track['artist'])
combined_data.append({
'spotify_track': track,
'youtube_music_track': yt_top_result['title'],
'youtube_music_id': yt_top_result['id']
})
# 結果をJSON形式で出力
with open('combined_data.json', 'w', encoding='utf-8') as f:
json.dump(combined_data, f, ensure_ascii=False, indent=2)
# combined_dataのデータを元にytmusicで"いいね"する
def likeYTMusicSongs(self):
# combined_dataからidだけ取得
# いいねした順が逆になってしまうのでreversed()で戻す
youtube_music_ids = [item["youtube_music_id"] for item in reversed(self.combined_data)]
for id in youtube_music_ids:
self.ytmusic.rate_song(videoId=id, rating = 'LIKE')
print(f"liked {id}")
__init__()
やってること
- spotifyapiの認証
- ytmusicapiの認証
- combined_data変数にcombined_data.jsonをロード
def __init__(self):
# Spotify APIの設定
SPOTIFY_CLIENT_ID = 'your client id'
SPOTIFY_CLIENT_SECRET = 'your client secret'
SPOTIFY_REDIRECT_URI = 'your redirect uri'
self.sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=SPOTIFY_CLIENT_ID,
client_secret=SPOTIFY_CLIENT_SECRET,
redirect_uri=SPOTIFY_REDIRECT_URI,
scope='user-library-read'))
# YTMusicの設定
# browser.jsonファイルが存在しなかったら作成
if not os.path.exists('browser.json'):
ytmusicapi.setup_oauth(filepath="browser.json")
# 作成したbrowser.jsonファイルで設定
self.ytmusic = ytmusicapi.YTMusic("browser.json")
# combined_data.jsonファイルが存在するかチェック
if os.path.exists('combined_data.json'):
# combined_data.jsonファイルが存在する場合はデータをロードする
with open('combined_data.json', 'r', encoding='utf-8') as f:
self.combined_data = json.load(f)
else:
# combined_data.jsonファイルが存在しない場合は空のリストを作成する
self.combined_data = []
spotifyAPIについては省略
SPOTIFY_CLIENT_ID,SPOTIFY_CLIENT_SECRET,SPOTIFY_REDIRECT_URIは自分で発行したやつに変えてください
ytmusicapiの認証はbrower.jsonを使うので、brower.jsonが無い初回は
# YTMusicの設定
# browser.jsonファイルが存在しなかったら作成
if not os.path.exists('browser.json'):
ytmusicapi.setup_oauth(filepath="browser.json")
でbrower.jsonを作る
# 作成したbrowser.jsonファイルで設定
self.ytmusic = ytmusicapi.YTMusic("browser.json")
作ったbrowser.jsonを読み込んでytmusicapiの設定終了
# combined_data.jsonファイルが存在するかチェック
if os.path.exists('combined_data.json'):
# combined_data.jsonファイルが存在する場合はデータをロードする
with open('combined_data.json', 'r', encoding='utf-8') as f:
self.combined_data = json.load(f)
else:
# combined_data.jsonファイルが存在しない場合は空のリストを作成する
self.combined_data = []
ytmusicapiで検索した結果と元の曲名を保存するcombined_data.jsonのロード
printJSON()
やってること
- _get_liked_tracks()でspotifyでいいねした曲を取得
- _search_youtube_music()でytmusicの検索結果を取得
- combined_data.jsonにspotifyの曲名、ytmusicの曲名、ytmusicのidを書き込む
# ytmusicの検索結果をjsonにして出力
def printJSON(self):
liked_tracks = self._get_liked_tracks()
combined_data = []
for track in liked_tracks:
yt_top_result = self._search_youtube_music(track['name'] + ' ' + track['artist'])
combined_data.append({
'spotify_track': track,
'youtube_music_track': yt_top_result['title'],
'youtube_music_id': yt_top_result['id']
})
# 結果をJSON形式で出力
with open('combined_data.json', 'w', encoding='utf-8') as f:
json.dump(combined_data, f, ensure_ascii=False, indent=2)
likeYTMusicSongs()
やってること
- initでロードしたcombined_dataからytmusicのidを抽出(いいね順もコピーするためにreversed()で反転しておく)
- ytmusic.rate_song(videoId=id, rating = 'LIKE')でytmusicで"いいね"する
# combined_dataのデータを元にytmusicで"いいね"する
def likeYTMusicSongs(self):
# combined_dataからidだけ取得
# いいねした順が逆になってしまうのでreversed()で戻す
youtube_music_ids = [item["youtube_music_id"] for item in reversed(self.combined_data)]
for id in youtube_music_ids:
self.ytmusic.rate_song(videoId=id, rating = 'LIKE')
print(f"liked {id}")
使い方
spotify2YTMusic = Spotify2YTMusic()
spotify2YTMusic.printJSON()
printJSON()を実行するとcombined_data.jsonが出力されるので、検索結果に間違いがなかったら、
spotify2YTMusic.likeYTMusicSongs()
でいいね実行して終わり
感想
spotifyからytmusicに移行するとき、700曲あるspotifyのいいねも移行するのがめんどくさいと思ったのが作るきっかけ
そういうサービスはすでにあるっぽいけど、自分の場合だとエラー起きたし簡単に作れそうだから作った
今回はytmusicapiがあったから簡単に作れたけど、全部自力でやったらかなりめんどくさそうだなと感じた
ytmusicapi様々
音楽系サブスクはアーティストのフォローもレコメンドに関わってくるので(多分)、アーティストのフォローを移行する機能もついでに作ったら良かったかも
参考資料