python

Бекап аудиозаписей с плейлиста ВКонтакте (до 6000) средствами Python и Vk API

  • пятница, 16 января 2015 г. в 02:11:01
http://habrahabr.ru/post/247987/

Здравствуйте.

Раньше часто слушал музыку средствами «Вконтакте» (далее ВК). После перехода на Ubuntu 14.10 возникли проблемы в виде полного зависания компьютера во время прослушивания аудиозаписей через браузер Google Chrome для linux систем. В связи с этим возникла необходимость забекапить свой плейлист для прослушивания музыки в оффлайн режиме. Для этих целей решил написать маленький скрипт на языке Python, которым можно будет не только скачивать музыку с нуля, но и обновлять существующую библиотеку.

Я использовал такие модули:
  • Selenium webdriver
  • requests
  • json
  • os

Собственно, начнем.

Сначала подключаем модули:

import os
import urllib2
import urllib
from selenium import webdriver
import json

Далее нужно получить access_token для выполнения запросов к API и получения необходимых нам прав доступа.
Перед этим нам нужно создать и активировать свое Standalone/Desktop приложение, id которого мы будем указывать в запросе.

Схема довольно простая: Мы открываем окно браузера, переходим по ссылке, вводим данные от аккаунта, разрешаем доступ, на выходе копируем необходимые данные с url(это access_token и expires_in — срок истекания токена).

Более детально о создании приложения и авторизации можно почитать здесь.

Я использовал selenium из-за собственной лени. У этого модуля достаточно функционала для автоматизации всех вышеуказанных действий. Вы можете использовать любой другой виртуальный браузер, который вам нравится.

Собственно код с комментариями:

# Создаем объект драйвера

driver = webdriver.Firefox()

# Переходим по ссылке.
# client_id - идентификатор созданного нами приложения
# scope - права доступа
driver.get("http://api.vkontakte.ru/oauth/authorize?"
           "client_id=4591034&scope=audio"
           "&redirect_uri=http://api.vk.com/blank.html"
           "&display=page&response_type=token")

user = "email/phone"
password = "password"

# Находим элементы формы и вводим данные для авторизации
user_input = driver.find_element_by_name("email")
user_input.send_keys(user)
password_input = driver.find_element_by_name("pass")
password_input.send_keys(password)

# Нажимаем на кнопку
submit = driver.find_element_by_id("install_allow")
submit.click()

# Получаем необходимые данные для выполнения запросов к api
current = driver.current_url
access_list = (current.split("#"))[1].split("&")
access_token = (access_list[0].split("="))[1] # acces_token
expires_in = (access_list[1].split("="))[1] # срок времени действия токена
user_id = (access_list[2].split("="))[1] # id нашей учетной записи в ВК
# Закрываем окно браузера

driver.close()

До недавнего времени «ВК API» возвращало все данные в формате xml, что было немного неудобным. Сейчас же ответы сериализируются в json словарь с которым можно без проблем работать. Здесь нам пригодится библиотека json, а конкретнее метод loads(), который преобразовывает строку в словарь.

Дальше план действий довольно простой:
  1. Выполняем запрос и получаем в ответе список всех аудиозаписей с плейлиста учетной записи (ограничение до 6000);
  2. Преобразовываем ответ в словарь;
  3. Берем необходимую информацию со словаря (исполнитель, название трека, ссылка на трек);
  4. Скачиваем аудиозаписи в нужную директорию, называя нужными названиями, а не стандартным набором букв, в котором хранится название трека.


Первый шаг:

# Принт для дебага
print "Connecting"
# Адрес запроса
url = "https://api.vkontakte.ru/method/" \
      "audio.get?uid=" + user_id +\
      "&access_token=" + access_token
# Создаем листы для хранения данных
artists_list = []
titles_list = []
links_list = []
# счетчик для дебага и перехода по элементам листов
number = 0
# Читаем ответ сервера и сохраняем в переменную
page = requests.get(url)
html = page.text

Второй шаг:

my_dict = json.loads(html) # используем loads()


Третий шаг, думаю все понятно без комментирования:

for i in my_dict['response']:
    artists_list.append(i['artist'])
    titles_list.append(i['title'])
    links_list.append(i['url'])
    number += 1

Четвертый и заключительный шаг:

# Создаем директорию, если она не была создана ранее

path = "downloads"

if not os.path.exists(path):
    os.makedirs(path)
# Принт для дебага
print "Need to download: ", number

# Процесс скачивания файлов

for i in range(0, number):

# Путь по которому будет храниться/скачиваться конкретная аудиозапись
    new_filename = path+"/"+artists_list[i] + " - " + titles_list[i] + ".mp3"
    print "Downloading: ", new_filename, i
# Проверка на существующий файл
    if not os.path.exists(new_filename):
# Сама загрузка файла, отсекаем из ссылки все аргументы и указываем путь куда скачивать
        with open(new_filename, "wb") as out:
            response = requests.get(links_list[i].split("?")[0])
            out.write(response.content)

print "Download complete."

Сейчас веду работу над самопальным плеером для прослушивания аудиозаписей с ВК (да, именно отдельный плеер, а не плагин для уже существующих популярных проигрывателей). В дальнейшем планирую написать статью, в которой будет описан процесс.

На этом все, спасибо за внимание.