Alvaros
.
- Регистрация
- 14.05.16
- Сообщения
- 21.452
- Реакции
- 101
- Репутация
- 204
Итак, в июле жизнь в стране наконец стала меняться к лучшему, ведь произошло то, чего многие жители с нетерпением ждали:
Но потоковая музыка появилась не вчера и наверняка есть такие, кто подсел на иглу Яндекса и пользуется подпиской на Яндекс.Музыку, которая впоследствии стала Яндекс.Плюсом.
Слушать песни стало удобно, подбираторы научились подбирать хорошие треки и это привело к накоплению библиотеки с плейлистами и прочих удобных штук, которые в новом сервисе нужно заново добавлять.
Eсли хочется попробовать, но вам тоже лень, то я расскажу как перенести пожитки быстро, бесплатно. Нужно всего лишь немного питонов с батарейками.
С помощью нехитрых приспособлений за пару дней у меня получилось сделать импортёр треков в Spotify и не потратить денег на soundiiz, на который почему-то внезапно возросла нагрузка.
Но есть нюансы.
API
Spotify предоставляет
В свою очередь у Яндекс.Музыки публичного API
Поэтому здесь мы немного пройдём по кривой дорожке, и воспользуемся приёмами с сомнительной репутацией.
А что Deezer?
У Deezer, к слову, публичный API управления библиотекой музыки тоже есть. Но нет готовой библиотеки для Python, которой можно было бы быстро и удобно воспользоваться.
Spotify
Здесь всё просто. Чтобы стать разработчиком, нужно получить ключ приложения
Там предложат добавить Redirect URI для OAuth, который можно установить любым, т.к. он нужен только для сервисов, обслуживающих сразу кучу людей, а в нашем случае всё происходит локально.
Яндекс.Музыка
Нужен логин и пароль для аккаунта, но если включена двухфакторная аутентификация, указывать надо Яндекс.Пароль из Яндекс.Ключа.
Работа приложения
Не хочется останавливаться на запуске приложений на Python, разворачивании виртуального окружения и т.п., поэтому опишу, как происходит импорт. Ссылка на репозиторий с программным кодом
Треки из 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 музыки пересекается с множеством базы композиций Яндекс.Музыки. Часть музыкальных дорожек может быть каверами/ремиксами и прочими извращениями, а часть просто внесёнными неправильно: не тот альбом, или порядок музыкантов разный.
Ещё проблем добавляет разный подход к составлению информации о треках: у Spotify альбом может быть только один, а Яндекс.Музыка отправляет массив альбомов. Исполнителей уже может быть несколько и там, и там.
Deezer предоставляет один альбом и одного исполнителя, но это уже другая история.
Поэтому используется следующий подход, чтобы и рыбку съесть, и на стул присесть:
Ненайденные мелодии, и нестандартные условия поиска звуковых дорожек выводятся в лог. Можно посмотреть, что именно добавилось и при необходимости обработать вручную.
Примечание
Этот проект по большому счёту необходим для одноразовой задачи, разрабатывался в свободное время, не для использования в промышленных приложениях, поэтому для бывалого специалиста код может показаться отвратительным.
Однако, при разработке практики PEP8 более-менее пытались соблюдаться, и общий размер программы довольно мал.
Актуальная версия Python на момент написания: 3.8.4
Использованные материалы:
You must be registered for see links
и ряде других стран.Но потоковая музыка появилась не вчера и наверняка есть такие, кто подсел на иглу Яндекса и пользуется подпиской на Яндекс.Музыку, которая впоследствии стала Яндекс.Плюсом.
Слушать песни стало удобно, подбираторы научились подбирать хорошие треки и это привело к накоплению библиотеки с плейлистами и прочих удобных штук, которые в новом сервисе нужно заново добавлять.
Eсли хочется попробовать, но вам тоже лень, то я расскажу как перенести пожитки быстро, бесплатно. Нужно всего лишь немного питонов с батарейками.
С помощью нехитрых приспособлений за пару дней у меня получилось сделать импортёр треков в Spotify и не потратить денег на soundiiz, на который почему-то внезапно возросла нагрузка.
Но есть нюансы.
API
Spotify предоставляет
You must be registered for see links
для своего сервиса Web API, и в том числе есть API для добавления к себе в библиотеку как плейлистов, так и избранных треков.В свою очередь у Яндекс.Музыки публичного API
You must be registered for see links
, но возможно конкуренция подстегнёт их предоставить доступ для сторонних разработчиков, потому что это нужно, удобно и полезно. Поэтому здесь мы немного пройдём по кривой дорожке, и воспользуемся приёмами с сомнительной репутацией.
А что Deezer?
У Deezer, к слову, публичный API управления библиотекой музыки тоже есть. Но нет готовой библиотеки для Python, которой можно было бы быстро и удобно воспользоваться.
Spotify
Здесь всё просто. Чтобы стать разработчиком, нужно получить ключ приложения
You must be registered for see links
.Там предложат добавить Redirect URI для OAuth, который можно установить любым, т.к. он нужен только для сервисов, обслуживающих сразу кучу людей, а в нашем случае всё происходит локально.
Яндекс.Музыка
Нужен логин и пароль для аккаунта, но если включена двухфакторная аутентификация, указывать надо Яндекс.Пароль из Яндекс.Ключа.
Работа приложения
Не хочется останавливаться на запуске приложений на Python, разворачивании виртуального окружения и т.п., поэтому опишу, как происходит импорт. Ссылка на репозиторий с программным кодом
You must be registered for see links
.Треки из 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») с тем же названием и в него добавляются все найденные мелодии.
Для плейлистов и сохранённых треков требуются разные разрешения:
- playlist-modify-private — для создания/модификации плейлистов
- user-library-modify — для добавления звуковых дорожек в избранное
Есть проблема: длина строки запроса ограничена, поэтому когда в плейлисте огромное количество песен, запрос завершается с ошибкой даже не начавшись. Чтобы избежать этой ситуации, список треков нарезается на части по 50 штук и добавление происходит несколькими запросами.
Метод search из API Spotify поддерживает ключевые слова для поиска по альбомам/исполнителям/названиям, чем и будем беззастенчиво пользоваться.
Поиск в Spotify
У Spotify большая база треков, но там есть не вся музыка. Можно легко догадаться, что множество отсутствующей в Spotify музыки пересекается с множеством базы композиций Яндекс.Музыки. Часть музыкальных дорожек может быть каверами/ремиксами и прочими извращениями, а часть просто внесёнными неправильно: не тот альбом, или порядок музыкантов разный.
Ещё проблем добавляет разный подход к составлению информации о треках: у Spotify альбом может быть только один, а Яндекс.Музыка отправляет массив альбомов. Исполнителей уже может быть несколько и там, и там.
Deezer предоставляет один альбом и одного исполнителя, но это уже другая история.
Поэтому используется следующий подход
- Для всех альбомов выполняется поиск по точному совпадению ключевых слов track:, artist:, album:.
Чаще всего этого достаточно. - Если трек не найден (или альбом у Яндекс.Музыки не указан), происходит попытка поиска без альбома.
- Если трек не не найден, происходит поиск со следующим исполнителем.
Ненайденные мелодии, и нестандартные условия поиска звуковых дорожек выводятся в лог. Можно посмотреть, что именно добавилось и при необходимости обработать вручную.
Примечание
Этот проект по большому счёту необходим для одноразовой задачи, разрабатывался в свободное время, не для использования в промышленных приложениях, поэтому для бывалого специалиста код может показаться отвратительным.
Однако, при разработке практики PEP8 более-менее пытались соблюдаться, и общий размер программы довольно мал.
You must be registered for see links
Актуальная версия Python на момент написания: 3.8.4
Использованные материалы:
- Иллюстрация Поросёнка Петра: Книга «Поросёнок Пётр и машина», Петрушевская Людмила
- Логотип Яндекс.Музыки: ООО «ЯНДЕКС»
- Логотип Spotify: Spotify AB



