Получение любимых аудиозаписей с pandora.com

    Для тех, кто не знает, pandora.com — интернет-радио, которое подбирает песни, согласно предпочтениям пользователей. Недавно один мой друг захотел скачать список любимых аудиозаписей. Но на самой пандоре, такой возможности нет. Поэтому пришлось влезть в ее нутро…


    Итак, с пандоры будем получать список названий песен и исполнителей, потом с помощью API контакта будем их скачивать.

    Шаг 1. Идем на пандору, и смотрим, что у нас происходит при запросе списка любимых песен. Наблюдаем такой запрос:
    Request URL:http://www.pandora.com/content/tracklikes?likeStartIndex=0&thumbStartIndex=5&webname=evgeny.vyalyy&cachebuster=1367100054190
    Request Method:GET
    Status Code:200 OK
    
    Request Headersview source
    Accept:*/*
    Accept-Charset:windows-1251,utf-8;q=0.7,*;q=0.3
    Accept-Encoding:gzip,deflate,sdch
    Accept-Language:ru,en-US;q=0.8,en;q=0.6
    Cookie:at=wNCFSbEDa7LTetjSbEwrXhkSGCSClV6j9vdiwaygcF8uwpsRlRg7usr3YsGsoHBfLJI3/y+zfNsMtHtvG5AA2Qg%3D%3D; v3ad=1:20:1:48206::5:0:0:0:505:011:MI:26163:0:1:0:0; __utma=118078728.1866197791.1367091864.1367091864.1367098565.2; __utmb=118078728.4.10.1367098565; __utmc=118078728; __utmz=118078728.1367091864.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); v2regbstage=true; atn=AT-1367099945481-858
    Host:www.pandora.com
    Proxy-Connection:keep-alive
    Referer:http://www.pandora.com/profile/likes/evgeny.vyalyy
    User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Ubuntu Chromium/25.0.1364.160 Chrome/25.0.1364.160 Safari/537.22
    X-Requested-With:XMLHttpRequest
    Query String Parametersview sourceview URL encoded
    likeStartIndex:0
    thumbStartIndex:5
    webname:evgeny.vyalyy
    cachebuster:1367100054190v
    


    Попробуем смоделировать этот запрос. Используем связку python requests + BeautifulSoup:

    resp = response.get("http://www.pandora.com/content/tracklikes?likeStartIndex=0&thumbStartIndex=5&webname=evgeny.vyalyy&cachebuster=1367100054190", 
        headers={"Cookie":"at=wNCFSbEDa7LTetjSbEwrXhkSGCSClV6j9vdiwaygcF8uwpsRlRg7usr3YsGsoHBfLJI3/y+zfNsMtHtvG5AA2Qg%3D%3D; v3ad=1:20:1:48206::5:0:0:0:505:011:MI:26163:0:1:0:0; __utma=118078728.1866197791.1367091864.1367091864.1367098565.2; __utmb=118078728.4.10.1367098565; __utmc=118078728; __utmz=118078728.1367091864.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); v2regbstage=true; atn=AT-1367099945481-858"})
    
    soup = BeautifulSoup.BeautifulSoup(resp.text)
    print soup
    


    Получаем много много не очень информативного html.

    Но наш запрос содержит как-то подозрительно много параметров. Попробуем чуть сократить:

    resp = response.get("http://www.pandora.com/content/tracklikes?likeStartIndex=0&thumbStartIndex=5&webname=evgeny.vyalyy", 
        headers={"Cookie":"at=wNCFSbEDa7LTetjSbEwrXhkSGCSClV6j9vdiwaygcF8uwpsRlRg7usr3YsGsoHBfLJI3/y+zfNsMtHtvG5AA2Qg%3D%3D;"})
    
    soup = BeautifulSoup.BeautifulSoup(resp.text)
    print soup
    


    Ура, ответ не изменился!
    Теперь, покопавшись в ответе, получаем, что вся информация хранится в div-е с классом infobox-body. Вот как выглядит этот div:

    <div class="infobox-body">
    <h3 class="s-0 line-h-1_4 normal">
    <a href="/lynyrd-skynyrd/live-from-freedom-hall/sweet-home-alabama-live-from-freedom-hall" class="first">Sweet Home Alabama (Live From Freedom Hall)</a>
    </h3>
    <p class="s-0 line-h-1_4">
    						by <a href="/lynyrd-skynyrd">Lynyrd Skynyrd</a>
    </p>
    <p class="s-0 line-h-1_4">
    <span class="profile_user_name">You</span> liked this on <a href="#" data-viewer-is-owner="true" data-station-id="1380018751859442317" class="like_context_stationname">The Offspring Radio</a>.
    	
    					</p>
    </div>
    


    Итак, теперь мы можем вытащить всю интересующую нас информацию:

    import re
    PATT = re.compile(">(.*?)<")
    for x in soup.findAll(attrs={"class":"infobox-body"}):
            print [PATT.findall(str(x.a))[0], PATT.findall(str(x.p.a))[0]]
    


    Первый шаг пройден! =)

    Шаг второй. Поиск и скачивание записей из vk.com

    Идем на vk.com/editapp?act=create и создаем новое приложение. Теперь надо получить access_token. Чтобы не мучаться, я решил получать access_token вручную, и просто вставлять его в тело скрипта. Итак, идем на
    oauth.vk.com/authorize?client_id=3608669&scope=audio&redirect_uri=https://oauth.vk.com/blank&display=wap&response_type=token

    Нас редиректит на новую страницу
    oauth.vk.com/blank.html#access_token=***&expires_in=86400&user_id=17738938


    Вытаскиваем из якоря интересующий нас access_token. Его мы будем использовать для запросов к vk.api.

    Пишем небольшую функцию поиска аудио:

    ACCESS_TOKEN = ***
    def audio_search(string):
        resp = r.get("https://api.vk.com/method/audio.search?q=%(q)s&sort=2&access_token=%(ACCESS_TOKEN)s"%{"q":string, "ACCESS_TOKEN":ACCESS_TOKEN})
        return resp.json()
    


    Она возвращает самый популярный результат поиска строки string(среди аудиозаписей).
    Ответ функции такой:

    >>> audio_search("My little horse")
    {u'response': [1, {u'album': u'27504721', u'artist': u'\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d', u'url': u'http://cs521522.vk.me/u3391535/audios/746ddef4902c.mp3', u'title': u'my little horse', u'duration': 208, u'aid': 159749117, u'owner_id': 3391535}]}
    


    Теперь мы знаем url для скачивания. Скачать можно с помощью стандартной функции urllib.urlretrieve.

    Итого получился вот такой скрипт:

    yadi.sk/d/7bP26GIQ4POa6

    Как с ним работать:

    1) Скрипт требует установленных пакетов requests и BeautifulSoup( sudo pip install requests BeautifulSoup)
    2) Нужно получить значение куки at =… с pandora.com (см. выше)
    3) Нужно получить ACCESS_TOKEN как это сделано выше
    4) Нужно установить параметр COUNT_OF_SONGS — число песен, которое хочется скачать (None, если надо скачать все)
    5) DOWNLOAD_FOLDER_NAME = «audio» — директория, куда будет сохраняться скачанная музыка.
    6) LOGIN — ваш логин на pandora.com

    Соответствующие параметры прописать в теле скрипта.
    Слушайте любимую музыку, и помните, что пиратство — грех =)

    UPD. Случайно забыл обновить логин коде. Извиняюсь
    UPD2 По просьбе юзера DenimTornado такой же скрипт для lastfm

    yadi.sk/d/U7kAZFZh4P5Yz

    Парметры для настройки:
    • COUNT_OF_SONGS = None — число песен. По умолчанию качать все (но не более 1000)
    • ACCESS_TOKEN = "" — см. выше как его получить
    • LOGIN = «sallyruthstruik» — твой логин на lastfm


    UPD3

    От юзера Setti:

    Доработанная версия для LastFM
    yadi.sk/d/tagClpSf4VsqQ

    + Добавлен BeautifulSoup в папку со скриптом. Теперь его устанавливать не обязательно
    + В старой версии поиск происходил только по имени трека. Теперь и по имени исполнителя. Иначе вконтакт выдаёт просто что попало.
    + Исправлено именование загружаемых файлов: удаляются спецсимволы
    + Обрезаются слишком длинные имена файлов
    + Выведены в отдельные настройки для lastfm запроса: лимит и страница. Теперь можно загружать пачками по 10, 50, 100, 500 и т.д. треков постранично. Если у вас слишком много треков, или вы хотите проследить за результатом скачивания на примере среза, задайте соответствующие параметры страницы и лимита
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 26
    • +3
      Спасибо, попробуем!

      п.с. А нет ли подобного, но с перламутровыми пуговками для LastFM? Очень хочется скопом скачать всё из Любимых треков.
      • +1
        Будет время — напишу тогда)
        • 0
          Заранее, спасибо!
          • 0
            Для пользователей Spotify тоже было бы интересно
            • 0
              Будет свободное время перепишу этот быдлокод в нормальном виде, и для пользователей Spotify тогда сделаю
        • 0
          > print [PATT.findall(str(x.a))[0], PATT.findall(str(x.p.a))[0]]
          Я уверен, есть более правильный и простой способ получения текстового содержимого тега. Тем более что здесь вы получаете его в html-кодированном виде.

          А еще ссылка на скрипт не работает. Код лучше размещать на gist.github.com
          • 0
            Ссылку починил

            Да, можно получать и так

            x.a.next, x.p.a.next

            Но по непонятной мне причине это работает в десятки раз медленней. Походу какой то баг в BeautifulSoup
            • 0
              Почему next? атрибуты contents[0] или string, судя по документации.
        • +1
          Зашёл на сайт, пишет в России сервис не доступен. :(
          • +8
            Надо установить расширение mediahint для Chrome.

            По умолчанию сайт доступен только из USA
            • 0
              Надо установить расширение mediahint для Chrome.

              Во-первых не только для Chrome, для Firefox тоже прекрасно работает.

              Во-вторых круто! Спасибо за наводку! А как это работает?
              • 0
                как работает само расширение я не знаю)
                • –12
                  Таак… Мечта о Spotify сбылась… Осталось сбыться мечте о Лепре…
                  • 0
                    Частичный прокси.
                    • 0
                      Только что зашёл на Pandora.com — шлёт нафиг (около месяца назад, когда писал предыдущий коммент — работало). Расширение Media Hint стоит и включено — проверил.
              • 0
                Была мысль распарсить tracksflow c целью качать музыку которая там играет. Но суть в том, что они не играют самый популярный результат с контакта а анализируют то, что вернул запрос, длину битрейт и тд. На этом мысль остановилась, остался только вариант с расширением для браузера, который будет собирать адреса mp3. В вашем случае нет такой проблемы как я понимаю?
                • 0
                  Кстати, раз уж речь зашла о пандоре, для ее прослушивания на маке круто использовать Tor+Hermes. По крайней мере мне очень нравится.
                  • 0
                    Последние года два я уже не слушаю музыку из папки Music, даже начинаю задумываться, а не грохнуть ли это 80ГБ чудовище вообще. Так как музыка у меня исключительно для фона — качество не слишком беспокоит, и di.fm через AIMP более чем достаточно.
                    От удаления удерживают ностальгия и паранойя насчет «а вдруг копирасты заблокируют» или «а вдруг завтра интернет сломают» и т.д. Периодически могу послушать что-то особо любимое, но довольно редко.
                    Pandora, в отличии от di.fm, понравилась отсутствием рекламы. Включаешь ambient, расслабляешься в выходные с утра, жена с малявкой постепенно просыпаются под негромкую спокойную музыку и тут по башке врубают балалайку «купите премиум аккаунт».
                    • 0
                      Многие любят слушать музыку в дороге, а качества мобильного интернета зачастую недостаточно)
                      • 0
                        В дороге у меня проще — езжу на общественном транспорте, слушаю аудиокниги. Вот для аудиокниг я специально написал парсер rutracker, который вытягивает оттуда все книги, приводит в некое подобие порядка авторов, жанры, информацию о длительности и т.д. Кеширует в локальной базе страницы с описанием книги и комментариями, дает возможность одним кликом скачать файл торрента и натравить на него uTorrent, сразу указав нужный путь сохранения с именем автора. Аудиокниг у меня сейчас намного больше, чем музыки.
                      • 0
                        Глядя на то как резко и в одночасье может измениться какой-то облачный сервис — хрен я грохну свою музыкальную коллекцию :)
                      • 0
                        А есть способ обойти или дополнить ограничение lastfm в 1000 треков? Нужно скачать 1100
                        • 0
                          Где то в коде, где отправляется запрос к lastfm api исправить 1000 на 1100 =)
                          • 0
                            Спасибо, но уже переписал треть скрипта.
                            Исправил кучу ошибок, которые и 50 треков не давали гладко скачать.
                            Так или иначе, спасибо вам за работу. Если б не ваш скрипт, то так до сих пор и не сделал бы папку с любимыми треками по списку который составлял с 2005 года.
                            Отдельные гемор — как «вктонтактеры» именуют музыкальные файлы. Сплошной facepalm. Так это у меня еще попсы не много. Иначе страшно даже представить.
                            Реальный пример имени файла: "♪ хачу новый гоод — Новогодние игрушки, свечи и хлопушки в нём… А весёлые зверюшки мой перевернули дом… Завели весёлый хоровод, до чего смешной лесной народ, и не верится, что всё пройдёт сказочным сном"
                        • 0
                          Доработанная версия для LastFM
                          yadi.sk/d/tagClpSf4VsqQ

                          + Добавлен BeautifulSoup в папку со скриптом. Теперь его устанавливать не обязательно
                          + В старой версии поиск происходил только по имени трека. Теперь и по имени исполнителя. Иначе вконтакт выдаёт просто что попало.
                          + Исправлено именование загружаемых файлов: удаляются спецсимволы
                          + Обрезаются слишком длинные имена файлов
                          + Выведены в отдельные настройки для lastfm запроса: лимит и страница. Теперь можно загружать пачками по 10, 50, 100, 500 и т.д. треков постранично. Если у вас слишком много треков, или вы хотите проследить за результатом скачивания на примере среза, задайте соответствующие параметры страницы и лимита

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.