- PVSM.RU - https://www.pvsm.ru -
Итак, в июле жизнь в стране наконец стала меняться к лучшему, ведь произошло то, чего многие жители с нетерпением ждали: Spotify запущен в России [1] и ряде других стран.
Но потоковая музыка появилась не вчера и наверняка есть такие, кто подсел на иглу Яндекса и пользуется подпиской на Яндекс.Музыку, которая впоследствии стала Яндекс.Плюсом.
Слушать песни стало удобно, подбираторы научились подбирать хорошие треки и это привело к накоплению библиотеки с плейлистами и прочих удобных штук, которые в новом сервисе нужно заново добавлять.
Eсли хочется попробовать, но вам тоже лень, то я расскажу как перенести пожитки быстро, бесплатно. Нужно всего лишь немного питонов с батарейками.
Люди порой бывают любопытными и пробуют различные вещи, в том числе новые программные продукты. Некоторым людям не хочется заниматься рутиной и поэтому они пишут программы, которые делают рутину за них. Иногда не за деньги.
В этом случае любопытство и необходимость автоматизировать рутину пересеклись.
У Spotify есть свои плюсы и минусы, как и у других сервисов. Есть функционал, которого нигде нет. Нет функций, которые есть где-то ещё.
Необходимость тех или иных фич — это вопрос субъективый, как субъективны музыкальные вкусы. Кому-то больше подходит библиотека в Яндекс.Музыке, кому-то в Spotify. Некоторые любят хранить библиотеку во флаке, кто-то любит винил, но некоторым подходит 144 кбит/с в Ogg Vorbis.
Алгоритмы подбора тоже могут в одном случае работать, а другие не работать лично для вас.
Поэтому вопрос о нужно/не нужно к тематике статьи имеет опосредованное отношение.
С помощью нехитрых приспособлений за пару дней у меня получилось сделать импортёр треков в Spotify и не потратить денег на soundiiz, на который почему-то внезапно возросла нагрузка.
Но есть нюансы.
Spotify предоставляет какую-никакую документацию [2] для своего сервиса Web API, и в том числе есть API для добавления к себе в библиотеку как плейлистов, так и избранных треков.
В свою очередь у Яндекс.Музыки публичного API нет [3], но возможно конкуренция подстегнёт их предоставить доступ для сторонних разработчиков, потому что это нужно, удобно и полезно.
Поэтому здесь мы немного пройдём по кривой дорожке, и воспользуемся приёмами с сомнительной репутацией.
Здесь всё просто. Чтобы стать разработчиком, нужно получить ключ приложения в консоли [4].
Там предложат добавить Redirect URI
для OAuth, который можно установить любым, т.к. он нужен только для сервисов, обслуживающих сразу кучу людей, а в нашем случае всё происходит локально.
Нужен логин и пароль для аккаунта, но если включена двухфакторная аутентификация, указывать надо Яндекс.Пароль из Яндекс.Ключа.
Не хочется останавливаться на запуске приложений на Python, разворачивании виртуального окружения и т.п., поэтому опишу, как происходит импорт. Ссылка на репозиторий с программным кодом в конце статьи [5].
Треки из API всех платформ приходят в разном формате, поэтому они приводятся к одинаковому представлению с минимально необходимым набором свойств:
class Track:
title = property(lambda self: self.__title)
album = property(lambda self: self.__albums[0] if len(self.__albums) > 0 else None)
artist = property(lambda self: self.__artists[0] if len(self.__artists) > 0 else None)
albums = property(lambda self: self.__albums)
artists = property(lambda self: self.__artists)
Плейлисты (включая избранное) тоже имеют одинаковый формат, и включают в себя итератор треков, чтобы удобно было использовать в циклах:
class Playlist:
class __iterator:
def __init__(self, playlist):
pass # заглушка для компактности
def __next__(self):
pass # заглушка для компактности
title = property(lambda self: self.__title)
tracks = property(lambda self: self.__tracks)
is_public = property(lambda self: self.__is_public)
def __len__(self):
return len(self.__tracks)
def __iter__(self):
return Playlist.__iterator(self)
def __getitem__(self, index):
return self.__tracks[index]
За взаимодействие с сервисами отвечает класс MusicProvider
:
class MusicProvider:
favorites = property(lambda self: self.__favorites)
playlists = property(lambda self: self.__playlists)
Класс YandexMusic (MusicProvider)
при инициализации загружает информацию по всем плейлистам и всем трекам в плейлисте «Мне понравилось».
Spotify (MusicProvider)
этого не делает, но содержит методы для импорта:
class Spotify(MusicProvider):
def import_playlist(self, playlist):
pass # заглушка для компактности
def import_favorites(self, playlist):
pass # заглушка для компактности
Внутри происходит поиск треков в базе Spotify с использованием данных о песнях, полученных из Яндекс.Музыки.
После того, как все треки плейлиста найдены, он создаётся (если это не «Liked Songs») с тем же названием и в него добавляются все найденные мелодии.
Для плейлистов и сохранённых треков требуются разные разрешения:
Есть проблема: длина строки запроса ограничена, поэтому когда в плейлисте огромное количество песен, запрос завершается с ошибкой даже не начавшись. Чтобы избежать этой ситуации, список треков нарезается на части по 50 штук и добавление происходит несколькими запросами.
Метод search
из API Spotify поддерживает ключевые слова для поиска по альбомам/исполнителям/названиям, чем и будем беззастенчиво пользоваться.
У Spotify большая база треков, но там есть не вся музыка. Можно легко догадаться, что множество отсутствующей в Spotify музыки пересекается с множеством базы композиций Яндекс.Музыки. Часть музыкальных дорожек может быть каверами/ремиксами и прочими извращениями, а часть просто внесёнными неправильно: не тот альбом, или порядок музыкантов разный.
Ещё проблем добавляет разный подход к составлению информации о треках: у Spotify альбом может быть только один, а Яндекс.Музыка отправляет массив альбомов. Исполнителей уже может быть несколько и там, и там.
Deezer предоставляет один альбом и одного исполнителя, но это уже другая история.
Поэтому используется следующий подход, чтобы и рыбку съесть, и на стул присесть:
track:
, artist:
, album:
.Ненайденные мелодии, и нестандартные условия поиска звуковых дорожек выводятся в лог. Можно посмотреть, что именно добавилось и при необходимости обработать вручную.
Этот проект по большому счёту необходим для одноразовой задачи, разрабатывался в свободное время, не для использования в промышленных приложениях, поэтому для бывалого специалиста код может показаться отвратительным.
Однако, при разработке практики PEP8 более-менее пытались соблюдаться, и общий размер программы довольно мал.
Актуальная версия Python на момент написания: 3.8.4
Автор: gudvinr
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/355160
Ссылки в тексте:
[1] Spotify запущен в России: https://newsroom.spotify.com/2020-07-14/spotify-is-now-available-in-russia-croatia-ukraine-and-10-other-european-markets/
[2] какую-никакую документацию: https://developer.spotify.com/documentation/web-api/
[3] нет: https://habr.com/en/post/462607/
[4] в консоли: https://developer.spotify.com/dashboard/
[5] в конце статьи: #sourcecode
[6] Исходные тексты программы: https://bitbucket.org/gudvinr/spothiefy
[7] Источник: https://habr.com/ru/post/511566/?utm_source=habrahabr&utm_medium=rss&utm_campaign=511566
Нажмите здесь для печати.