Недавно мне захотелось поработать с «Яндекс Музыкой» не через браузер. Как выяснилось, у них нет открытого api, и дело оказалось не тривиальным. Да и ничего готового найти не удалось.
Те, кому лень читать, могут сразу перейти к результату — python-yamusic.
Для начала я вооружился firebug'ом и проследил, куда идут запросы. Были найдены основные направления:
Полученные первыми тремя запросами данные легко отфильтровать при помощи Beautiful Soup, так как:
Мою реализацию парсера можно посмотреть в коде.
Теперь кажется, что всё просто. Делаем запрос на storage.music.yandex.ru/getstorage dir трека/2.xml и получаем xml'ку вида:
Теперь делаем запрос storage.music.yandex.ru/download-infostorage dir трека/filename трека и получаем ещё одну xml'ку:
Но, посмотрев запросы на скачку трека, стало понятно, что тут не все данные.
Пролистав javascript, я нашёл функцию, которая из пути без первого символа и параметра s создаёт нужный нам ключ. Эту функцию было лень переписывать на python, поэтому она просто выполняется через QScript.
Сейчас, имея все данные, можно составить url трека: http://хост/get-mp3/ключ/параметр tsпуть?track-id=id трека&\region=регион&from=service-search, но просто так скачать файл не удастся. Не долго думая, я решил попробовать делать всё в одной сессии — всё сразу получилось. Результатом вышла библиотека python-yamusic
Это очень просто, для начала нужно инициировать Qt приложение и сделать все импорты:
Для поиска есть:
Для получения данных из найденных объектов:
И, собственно, для открытия трека:
PS &\region написано из-за ®ion
Те, кому лень читать, могут сразу перейти к результату — python-yamusic.
Анализируем работу
Для начала я вооружился firebug'ом и проследил, куда идут запросы. Были найдены основные направления:
- music.yandex.ru/fragment/search?text=поисковый запросс&type=тип&page=страница, где возможны 3 типа: tracks, albums и artists; остальные параметры и так понятны. Это поисковый запрос, из результата которого мы можем получить id песен, альбомов и артистов;
- music.yandex.ru/fragment/artistid артиста/tracks — страница со всеми треками и альбомами исполнителя;
- music.yandex.ru/fragment/albumid альбома — страница альбома;
- storage.music.yandex.ru/getstorage dir трека/2.xml — xml с названием файла и длиной трека;
- storage.music.yandex.ru/download-infostorage dir трека/filename трека — xml с данными для загрузки трека;
- непонятный и всегда разный адрес трека.
Полученные первыми тремя запросами данные легко отфильтровать при помощи Beautiful Soup, так как:
- все треки лежат в div'ах с классом b-track со всеми данными в свойстве onclick(отсюда мы получаем его storage dir и id);
- альбомы находятся в div'ах с классом b-albums;
- исполнители в div'ах с классом b-artist-group.
Мою реализацию парсера можно посмотреть в коде.
Скачиваем трек
Теперь кажется, что всё просто. Делаем запрос на storage.music.yandex.ru/getstorage dir трека/2.xml и получаем xml'ку вида:
<?xml version="1.0" encoding="utf-8"?>
<track filename="название файла, обычно 2.mp3" track-length="длина трека" />
Теперь делаем запрос storage.music.yandex.ru/download-infostorage dir трека/filename трека и получаем ещё одну xml'ку:
<download-info>
<host>хост</host>
<path>путь</path>
<ts>параметр ts</ts>
<region>регион</region>
<s>параметр s</s>
</download-info>
Но, посмотрев запросы на скачку трека, стало понятно, что тут не все данные.
Пролистав javascript, я нашёл функцию, которая из пути без первого символа и параметра s создаёт нужный нам ключ. Эту функцию было лень переписывать на python, поэтому она просто выполняется через QScript.
Сейчас, имея все данные, можно составить url трека: http://хост/get-mp3/ключ/параметр tsпуть?track-id=id трека&\region=регион&from=service-search, но просто так скачать файл не удастся. Не долго думая, я решил попробовать делать всё в одной сессии — всё сразу получилось. Результатом вышла библиотека python-yamusic
Использование библиотеки
Это очень просто, для начала нужно инициировать Qt приложение и сделать все импорты:
>>> from yamusic.app import Search, cursor
>>> from PySide.QtCore import QCoreApplication
>>> import sys
>>> app = QCoreApplication(sys.argv)
Для поиска есть:
>>> cursor.search(Search.TYPE_ARTISTS, 'query')
>>> cursor.search(Search.TYPE_ALBUMS, 'query')
>>> cursor.search(Search.TYPE_TRACKS, 'query')
Для получения данных из найденных объектов:
>>> artist.get_albums()
>>> artist.get_tracks()
>>> album.get_tracks()
И, собственно, для открытия трека:
>>> track.open()
PS &\region написано из-за ®ion