kimagre inrash

感想を書きます

AmazonMusicのマイミュージックをSpotifyに移行しよう(Python+Selenium)

time 2021/09/21

最近、「サブスク解禁!」と言われてAmazonMusicを見に行くものの、AmazonMusicには非対応なことが多くなってきました。
特にこだわる理由もないのでAmazonMusicからの離脱をすることに。

ざっくり比較した感じ、Spotifyが良さそう。値段も一緒で980円なので。

AmazonMusicからマイミュージックをエクスポート

マイミュージック、いわゆるいいねした曲をそのまま移行したい。
確認してみると約500曲もありました。手作業で移行するのはちょっとツラいです。
ということでなんとかしてエクスポートできる方法を考えます。

パッと思いついたのが、Python+Seleniumでデータを取得する方法。
AmazonMusicはアプリ以外にもブラウザからも閲覧できるのでこの方法で取得できそうです。

なお、ここからは自己責任で。

# -*- coding: utf-8 -*-
import os
import time

import chromedriver_binary
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys

if __name__ == "__main__":
    # Seleneium ユーザーデータ(キャッシュ)
    user_data_folder = os.getcwd() + "\\UserData"
    profile_folder_name = "Default"
    if not os.path.exists(user_data_folder):
        os.mkdir(user_data_folder)

    # webdriver の設定
    options =  webdriver.ChromeOptions()
    options.add_argument('--user-data-dir=' +  user_data_folder)
    options.add_argument('--profile-directory=' + profile_folder_name)

    browser = webdriver.Chrome(options=options)

    # 出力ファイル
    f = open('plist.txt','w', encoding='UTF-8') 

    # AmazonMusic
    url = "https://music.amazon.co.jp/my/songs"
    tempTitle = ""

    # URLにアクセス
    browser.get(url)

    while True:
        # 待機
        time.sleep(5)

        trs = browser.find_elements_by_tag_name("music-image-row")
        index = 1
        length = len(trs)
        for tr in trs:
            print(str(index) + "/" + str(length))

            musicLinks = tr.find_elements_by_tag_name("music-link")

            if index == 1:
                temp = musicLinks[0].get_attribute("title")
                if temp == tempTitle:
                    url = "" # ループ終了
                tempTitle = temp

            newLine = True
            for ml in musicLinks:
                title = ml.get_attribute("title")
                if len(title) > 0:
                    f.write(title + "\t")
                else:
                    newLine = False
                    break

            if newLine == True:
                f.write("\n")
            index+=1

        # PageDown
        body = browser.find_element_by_css_selector('body')
        body.send_keys(Keys.PAGE_DOWN)

        # 次のページがあるか
        if len(url) == 0:
            break

    f.close()

    # プラウザを閉じる
    browser.quit()

Visual Studio Codeから実行することを想定。
初回起動時は time.sleep(5) のところにブレイクポイントを貼ってブラウザを手動で操作し、ログインさせる必要があります。

Seleniumのユーザーデータ(キャッシュ)を保存してますが、通常は必要ないと思います。
(デバッグの度にログインするのが手間だったので機能として入れてました)

1回で50曲くらいしか取得できないので「PageDownキー」で動かしています。
なお、私がやったときはスクロール量が足りず重複したので後ほど手動で plist.txt の重複分を整理しました。

手動要素が多いのは1回限りのため。
これが何回も繰り返すものであれば、対策も考えましたが・・ともかくエクスポートできました。

Spotifyのマイライブラリに登録する

こちらも同様にブラウザから閲覧・操作が出来る模様。
一応、APIが用意されているけれど、覚えることが多そうだったのでSeleniumでサクっと。

# -*- coding: utf-8 -*-
import csv
import os
import time

import chromedriver_binary
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys

if __name__ == "__main__":
    # Seleneium ユーザーデータ(キャッシュ)
    user_data_folder = os.getcwd() + "\\UserData"
    profile_folder_name = "Default"
    if not os.path.exists(user_data_folder):
        os.mkdir(user_data_folder)

    # webdriver の設定
    options =  webdriver.ChromeOptions()
    options.add_argument('--user-data-dir=' +  user_data_folder)
    options.add_argument('--profile-directory=' + profile_folder_name)

    # URLにアクセス
    browser = webdriver.Chrome(options=options)
    url = "https://open.spotify.com/search"
    browser.get(url)

    # リストを読み込む
    # csvファイル
    csv_file = open("plist.txt", "r", encoding="UTF-8", errors="", newline="" )
    # リスト形式
    fcsv = csv.reader(csv_file, delimiter="\t", doublequote=True, lineterminator="\r\n", quotechar='"', skipinitialspace=True)
    list_of_rows = list(fcsv)

    index = 1
    length = len(list_of_rows)
    for row in list_of_rows:
        print(str(index) + "/" + str(length) + " " + row[0] + " " + row[1] )

        # 待機
        time.sleep(5)

        # 検索
        search = browser.find_element_by_css_selector(".dIwMadpRrW1PwEwEeAbN.__whSyV64vHUPUxZSpRJ")
        search.clear()
        time.sleep(1)
        search.send_keys( row[0] + " " + row[1] )

        # 待機
        time.sleep(5)

        # いいね
        musics = browser.find_elements_by_xpath("/html/body/div[4]/div/div[2]/div[3]/main/div[2]/div[2]/div/div/div[2]/div/div/div/section[2]/div[2]/div/div/div/div[2]/div[1]/div/div[2]/button[1]")
        if len(musics) > 0:
            # 一番最初に見つかったものとする
            musics[0].click()

        # 待機
        time.sleep(2)

        index+=1

    # プラウザを閉じる
    browser.quit()

こちらもVisual Studio Codeから実行することを想定。
基本は一緒で最初の time.sleep(5) でブレイクポイントを貼って手動でログイン処理

その後、「検索」で一番上に見つかったものに「いいね」をしてマイライブラリに登録する形。
試しにやってみて異なるアレンジの曲が登録されてたりしましたが、まあ良しとします。

なお、たまに「いいね」出来ない時があったので完璧ではないです。

約500曲中470曲はこれで移行出来ました。
移行できなかった30曲はなんだったのだろう・・?
見つからなかった場合にトレース出すとかすれば良かったなあ。

Spotifyからさらに移行することも考えてSeleniumでマイライブラリのエクスポートも試しましたが、「PageDownキー」が効かない。
ホイールでしか動かせないっぽいので一旦保留。
APIが用意されているのでそちらで吸収しようかな。

とりあえずこれでB’zやZARDが聴けます!(iTunesにほとんど入ってはいるけど)

追記(2021.09.22)

SpotifyのAPIを使ってマイライブラリをエクスポートしました。

前後記事

Windows10 + Selenium + Python + ChromeDriverでブラウザを自動操作
Spotifyのマイライブラリをエクスポートしよう(Python)