Доброго времени суток всем.
Захотелось мне скачать всю мою музыку со ВКонтакте на флешку, как в старые добрые времена. Немного погуглив и не найдя практически ничего более менее приемлемого, я решил действовать своими силами. Спустя пол часа получился вполне себе рабочий скрипт. Итак, начнём.
Для работы нужно скачать модули 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()
Я только учусь, поэтому буду рад всем замечаниям в коде. Спасибо за внимание.