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