Как стать автором
Поиск
Написать публикацию
Обновить

Загрузка музыки ВКонтакте

Время на прочтение6 мин
Количество просмотров27K

Доброго времени суток всем.


Захотелось мне скачать всю мою музыку со ВКонтакте на флешку, как в старые добрые времена. Немного погуглив и не найдя практически ничего более менее приемлемого, я решил действовать своими силами. Спустя пол часа получился вполне себе рабочий скрипт. Итак, начнём.


Для работы нужно скачать модули vk_api и request!


Для начала подключим необходимые модули и объявим некоторые переменные:


import os
import pickle
import vk_api
import requests

from vk_api import audio

from time import time

vk_file = "vk_config.v2.json"
REQUEST_STATUS_CODE = 200 
path = 'vk_music/'

Теперь напишем метод авторизации в аккаунт ВКонтакте:


def Auth(new=False):
    try:
        USERDATA_FILE = r"AppData/UserData.datab" #файл хранит логин, пароль и id
        global my_id # объявляем переменную глобально, дабы иметь к ней доступ из других методов
                # проверяем, нет ли сохранённых данных авторизации? Если есть, то загружаем
        if (os.path.exists(USERDATA_FILE) and new == False):
            with open(USERDATA_FILE, 'rb') as DataFile:
                LoadedData = pickle.load(DataFile)

            login = LoadedData[0]
            password = LoadedData[1]
            my_id = LoadedData[2]
        else: # если есть, но пользователь выбрал новую авторизацию, то удаляем данных и просим ввести новые
            if (os.path.exists(USERDATA_FILE) and new == True):
                os.remove(USERDATA_FILE)

            login = str(input("Введите логин\n> ")) 
            password = str(input("Введите пароль\n> ")) 
            my_id = str(input("Введите id профиля\n> "))
            SaveUserData(login, password, my_id)

        SaveData = [login, password, my_id]
        with open(USERDATA_FILE, 'wb') as dataFile:
            pickle.dump(SaveData, dataFile) # сохраняем введённые данные

        vk_session = vk_api.VkApi(login=login, password=password)
        try:
            vk_session.auth() # пробуем авторизоваться, если возникнет исключение, значит у пользователя включена двухфакторная аутентификация. Просим ввести код.
        except:
            vk_session = vk_api.VkApi(login=login, password=password, 
                auth_handler=auth_handler) # auth_handler=auth_handler - вызываем метод, см. далее
            vk_session.auth()
        print('Вы успешно авторизовались.')
        vk = vk_session.get_api()
        global vk_audio # объявляем глобально, дабы иметь доступ из других методов
        vk_audio = audio.VkAudio(vk_session)
    except KeyboardInterrupt:
        print('Вы завершили выполнение программы.')

Метод будет проверять, не авторизовывались ли мы уже раньше? Если такое было, то можно будет продолжить в этом аккаунте, или авторизоваться по-новой. В этом случае старые данные будут стёрты.


Далее напишем метод auth_handler, который нужен для авторизации в аккаунтах, в которых включена двухфакторная аутентификация:


def auth_handler():
    code = input("Введите код подтверждения\n> ")
    remember_device = True # True -  запоминаем и не просим каждый раз вводить код
    return code, remember_device

И так, теперь мы можем авторизоваться во ВКонтакте. В методе Auth упомянался метод SaveUserData(), он нужен для сохранения данных. Напишем его:


def SaveUserData(login, password, profile_id):
    USERDATA_FILE = r"AppData/UserData.datab"
    if (not os.path.exists("AppData")): # если нет папки AppData - создадим ее
        os.mkdir("AppData")

    SaveData = [login, password, profile_id] # список данных для сохранения

    with open(USERDATA_FILE, 'wb') as dataFile: # собственно записываем данные в файл
        pickle.dump(SaveData, dataFile)

Данные будут записаны в бинарном виде, дабы не хранить логин и пароль пользователя в открытом виде.


Осталось написать метод загрузки аудио со ВКонтакте, давайте это и сделаем:


def main():
    try:
        if (not os.path.exists("AppData")):
            os.mkdir("AppData")
        if not os.path.exists(path):
            os.makedirs(path)
                # спросим пользователя, нужно ли авторизоваться по-новой или продолжить старую сессию
        auth_dialog = str(input("Авторизоваться заново? yes/no\n> "))
        if (auth_dialog == "yes"):
            Auth(new=True)
        elif (auth_dialog == "no"):
            Auth(new=False)
        else:
            print('Ошибка, неверный ответ.')
            main()
        print('Подготовка к скачиванию...')
        os.chdir(path) #меняем текущую директорию

        audio = vk_audio.get(owner_id=my_id)[0]
        print('Будет скачано:', len(vk_audio.get(owner_id=my_id)), 'аудиозаписей.')
        count = 0
        time_start = time()
        print("Скачивание началось...\n")
                # этим циклом, собственно, и скачиваем нашу музыку.
        for i in vk_audio.get(owner_id=my_id):
            try:
                print('Скачивается: ' + i["artist"] + " - " + i["title"])
                count += 1
                r = requests.get(audio["url"])
                if r.status_code == REQUEST_STATUS_CODE:
                    print('Скачивание завершено: ' + i["artist"] + " - " + i["title"])
                    with open(i["artist"] + ' - ' + i["title"] + '.mp3', 'wb') as output_file:
                        output_file.write(r.content)
            except OSError:
                print("!!! Не удалось скачать аудиозапись №", count)
        time_finish = time()
        print("" + vk_audio.get(owner_id=my_id) + " аудиозаписей скачано за: ", 
                                            time_finish - time_start + " сек.")
    except KeyboardInterrupt:
        print('Вы завершили выполнение программы.')

Ну вот и всё. Теперь у нас есть рабочий скрипт для загрузки аудиозаписей из ВКонтакте.
Вот так выглядит весь исходный код:


Показать исходный код
import os
import pickle
import vk_api
import requests

from vk_api import audio

from time import time

__version__ = 'VK Music Downloader v1.0'

APP_MESSAGE = '''
        _   .   ___
    /\\   |   | | \\  |  |   |  \\    /  | /
   /__\\  |   | |  \\ |  |   |   \\  /   |/
  /    \\ |___| |__/ |  |___|    \\/    |\\
  '''

vk_file = "vk_config.v2.json"
REQUEST_STATUS_CODE = 200 
path = 'vk_music/'

def auth_handler(remember_device=None):
    code = input("Введите код подтверждения\n> ")
    if (remember_device == None):
        remember_device = True
    return code, remember_device

def SaveUserData(login, password, profile_id):
    USERDATA_FILE = r"AppData/UserData.datab"
    SaveData = [login, password, profile_id]

    with open(USERDATA_FILE, 'wb') as dataFile:
        pickle.dump(SaveData, dataFile)

def Auth(new=False):
    try:
        USERDATA_FILE = r"AppData/UserData.datab" #файл хранит логин, пароль и id
        global my_id
        if (os.path.exists(USERDATA_FILE) and new == False):
            with open(USERDATA_FILE, 'rb') as DataFile:
                LoadedData = pickle.load(DataFile)

            login = LoadedData[0]
            password = LoadedData[1]
            my_id = LoadedData[2]
        else:
            if (os.path.exists(USERDATA_FILE) and new == True):
                os.remove(USERDATA_FILE)

            login = str(input("Введите логин\n> ")) 
            password = str(input("Введите пароль\n> ")) 
            my_id = str(input("Введите id профиля\n> "))
            SaveUserData(login, password, my_id)

        SaveData = [login, password, my_id]
        with open(USERDATA_FILE, 'wb') as dataFile:
            pickle.dump(SaveData, dataFile)

        vk_session = vk_api.VkApi(login=login, password=password)
        try:
            vk_session.auth()
        except:
            vk_session = vk_api.VkApi(login=login, password=password, 
                auth_handler=auth_handler)
            vk_session.auth()
        print('Вы успешно авторизовались.')
        vk = vk_session.get_api()
        global vk_audio 
        vk_audio = audio.VkAudio(vk_session)
    except KeyboardInterrupt:
        print('Вы завершили выполнение программы.')

def main():
    try:
        if (not os.path.exists("AppData")):
            os.mkdir("AppData")
        if not os.path.exists(path):
            os.makedirs(path)

        auth_dialog = str(input("Авторизоваться заново? yes/no\n> "))
        if (auth_dialog == "yes"):
            Auth(new=True)
        elif (auth_dialog == "no"):
            Auth(new=False)
        else:
            print('Ошибка, неверный ответ.')
            main()
        print('Подготовка к скачиванию...')
        os.chdir(path) #меняем текущую директорию

        audio = vk_audio.get(owner_id=my_id)[0]
        print('Будет скачано:', len(vk_audio.get(owner_id=my_id)), 'аудиозаписей.')
        count = 0
        time_start = time() # сохраняем время начала скачивания
        print("Скачивание началось...\n")
                # собственно циклом загружаем нашу музыку 
        for i in vk_audio.get(owner_id=my_id):
            try:
                print('Скачивается: ' + i["artist"] + " - " + i["title"]) # выводим информацию о скачиваемой в данный момент аудиозаписи
                count += 1
                r = requests.get(audio["url"])
                if r.status_code == REQUEST_STATUS_CODE:
                    print('Скачивание завершено: ' + i["artist"] + " - " + i["title"])
                    with open(i["artist"] + ' - ' + i["title"] + '.mp3', 'wb') as output_file:
                        output_file.write(r.content)
            except OSError:
                print("!!! Не удалось скачать аудиозапись №", count)
        time_finish = time()
        print("" + vk_audio.get(owner_id=my_id) + " аудиозаписей скачано за: ", 
                                            time_finish - time_start + " сек.")
    except KeyboardInterrupt:
        print('Вы завершили выполнение программы.')

if __name__ == '__main__':
    print(APP_MESSAGE)
    print(__version__ + "\n")
    main()

Я только учусь, поэтому буду рад всем замечаниям в коде. Спасибо за внимание.

Теги:
Хабы:
Всего голосов 45: ↑36 и ↓9+27
Комментарии50

Публикации

Ближайшие события