Делаем бэкап музыкальной базы vkontakte с помощью Python

в 6:24, , рубрики: python, метки:

Год назад я захотел в машину флешку с винегретом из музыки, которая была у меня в плейлисте контакта. А там, к слову, почти 1400 треков.

Итак, первое, что я сделал — октрыл список расширений оперы и набрал в поиске «vkontakte». Но вот оказия, все приложения предлагали качать по одному треку, в основном добавляя рядом с ним кнопочку «скачать». В принципе, это удобно, если надо стянуть оттуда один-два трека, но вот если их 1400…

Следующий моим шагом было открытие страницы с музыкой и внимательная медитация над ней, с целью распарсить страницу, выдрав оттуда ссылки и названия. Слегка подумав, я решил, а почему бы снова не использовать вконтактовый API? Ведь опыт использования у меня уже есть (писал десктопный плеер на Qt). Но лепить полноценное приложение, тем более на плюсах или каком-либо другом языке, мне показалось слегка не умным решением. И тут я подумал — черт возьми, есть же python, наклепаю скрипт и стяну все. Итак, выбор сделан, начинаем кодить.

Открываем Geany и пишем первые строчки… И вот тут-то моя фантазия и желание лепить комбайны из ничего опять разыгрались. Дальше под катом.

Итак, редактор открыт, мозги работают, в наушниках играет Judas Priest, и из под моего пера выходит очередное произведение.

Так как на рабочих станциях, компьютерах и ноутбуках у меня виндой и не пахнет, так как везде стоит линукс, было решено использовать штатный wget для загрузки. Да и консольный выхлоп у него красивый.

Для начала я решил сделать небольшую функцию, которая проверит подключение к интернету. Для этого попытаемся открыть google.com.

def checkConnection():  #Функция, проверяющая наличие подключения к интернету.
	try:
		response = urllib2.urlopen('http://google.com', timeout = 1)
		return True
	except urllib2.URLError as err: pass
	return False

Если гугл открылся — функция возвращает true, если нет — false.

Дальше моея несгибаемая фантазия решила влепить еще одну проверку, на этот раз на наличие в системе wget.

def checkWget(): #Проверяется наличие в системе wget
	print "Проверяю наличие wget. Сейчас будет скачана какая-то пое**нь..."
	testfilename = "x_8091546b.jpg"
	cmd = "wget http://cs5705.vkontakte.ru/u403273/139647416/x_8091546b.jpg"
	os.popen(cmd)
	chk = os.path.exists(testfilename)
	if chk == True:
		print "Да, wget у тебя, как видишь, стоит. Все пучком, приступаем!"
		os.remove(testfilename)
	else:
		print "Ну вот, не стоит. Ставь wget, а потом уже лезь качать что-то!"
		exit()
	
	return

Итак, функции проверок готовы, начинаем сам процесс закачки. Фантазия решила добавить в срипт немного юмора, чтоб все было не так банально, как всегда, и, собственно, вот результат.

Не мудрствуя лукаво, я решил использовать для авторизации на серверах контакта штатный системный браузер, а не делать это все средствами питона, так как мне показалось, что это будет быстрее и удобнее, тем более, что скрипт запускаться будет не каждый день.

print "Привет, юзер! Ты запустил скрипт grabVK. Сейчас мы с тобой скачаем музло с твоей страницы."
print "Данный скрипт скачивает все подряд музло, делая, скажем так, бэкап музыки с твоей страницы."
print "Ну а дальне ты сможешь слушать свои же записи где хочешь и каким хочешь плеером"
print "Ну что ж, начнем"
print " "
print "Проверяю подключение к интернету..."

inON = checkConnection()  #Проверяем подключение к инету.
if inON == True:
	print "К интернетам подключен!"
else:
	print "К сожалению, к интернетам ты не подключен. Поэтому иди нафиг, пока не подключишься =)"
	exit()
	
print "Итак, если подключение к интеренту найдено, приступим к процессу загрузки"
print "Напомню, что для правильно работы скрипта, в ней должен быть установлен wget!"
print "Есть ли у тебя в системе wget?"
print "Если ты уверен, что у тебя стоит - смело жмакай y, если нет - n, тогда я проверю сам =)"

answer = raw_input("Стоит ли у тебя wget?: ")
if answer == "y":
	print "Ну раз стоит, так стоит. Не шуми потом, если ничего не выйдет!"
else:
	checkWget()

print "Мы же хотим по-быстрому скачать музыку, так? Поэтому было решено не клепать велосипедов и открыть нужные ссылки в системной браузере"
print "Но есть один нюанс - после того, как откроется браузер и ты пройдешь авторизацию - не закрывай его сломя голову!"
print "После прохождения авторизации ты видишь непонятную строчку на экране, так? Молодец!"
print "В строчке, как ты можешь видеть, есть три параметра, это access_token, expires_in и user_id, разделенные знакои & "
print "Скопируй по очереди эти параметры и введи в соответствующие поля скрипта, нажав ентер"

answer = raw_input("Готов?: ")
if answer == "y":
	print "Вот и хорошо, продолэжаем!"
else:
	print "Вот же какой трусливый! Ну и ладно!"
	exit()
	
webbrowser.open_new_tab("http://api.vkontakte.ru/oauth/authorize?client_id=2223684&scope=audio&redirect_uri=http://api.vk.com/blank.html&display=page&response_type=token")

access_token = raw_input("access_token: ")
print "Малаца, теперь копипасть expires_in."
expires_in = raw_input("expires_in: ")
print "Ну ваще мегакулхацкер прям! Остался последний параметр."
user_id = raw_input("user_id: ")
print "Миссия завершена! Таперича начинаем дергать музло. Точнее пока что коннектиться и дратьс писок. Вперде!"

print "Ну, была не была, коннектимся!"

Итак, при выполнении этого кода открывается системный браузер, который показывает страницу авторизации на сервере API vkontakte. Для того, чтоб сработала авторизация, надо создать приложение vkontakte, которому будет присвоен ID, его нужно указать в ссылке авторизации. У меня такое приложение было создано давно, еще для декстопного плеера. В браузере появляется строка с тремя отданными сервером параметрами, которые нужно передать скрипту методом копипаста, они необходимы для получения базы в XML формате.

Параметры получены, все готово к тому, чтоб получить список и распарсить его. Для парсинга XML использована Lxml.

url = "https://api.vkontakte.ru/method/audio.get.xml?uid=" + user_id + "&access_token=" + access_token
page = urllib2.urlopen(url)
html = page.read()

print "Список музла получен, парсим..."

artistMas = []
titleMas = []
urlMas = []
number = 0

print "Парсим на предмет исполнителей..."

doc  = lxml.html.document_fromstring(html)
for artist in doc.cssselect('artist'):
	artistMas.append(artist.text)
	number = number + 1
	
print "OK"
print "Парсим на предмет названий..."

for title in doc.cssselect('title'):
	titleMas.append(title.text)
	
print "OK"
print "Парсим на предмет ссылок..."

for urlm in doc.cssselect('url'):
	urlMas.append(urlm.text)
	
print "OK"

print "" 

Нами были получены списки артистов, треков и ссылок. Самое время начать закачку. Закачка будет производиться в каталог download. Также реализована докачка — если в каталоге download уже лежат музыкальные файлы, они не будут закачиваться заново и будут пропущены, что удобно, если надо просто иногда синхронизировать плейлист vkontakte с локальным.

print "Ну вот, теперь приступаем к даунлоадингу! Помни, юзер, что скачается весь плейлист!"
print "Т.е. если у тебя дофига записей и медленный интернет - забей на это дело и жди гуевую"
print "морду, где можно будет качать выборочно"

	
path = "download"
if os.path.exists(path):
	"Папка уже есть, начинаем докачку "
else:
	os.makedirs(path)

print "Нам нужно скачать кучу файлов. Вычисляем количество..."
print number

answer = raw_input("Готов?: ")
if answer == "y":
	print "Пошла закачка, пошла родимая!"
else:
	print "Вот же какой трусливый! Ну и ладно!"
	exit()


for i in xrange(0, number-1):
	print "Загружается:"
	print i
	print " "
	
	filename_new = path+"/"+artistMas[i]+ " - " + titleMas[i] + ".mp3";
	if os.path.exists(filename_new):
		print "Этот файл уже загружен, переходим к следующему"
	else:				
		downCmd = "wget -P" + path + " " + urlMas[i]
		os.popen(downCmd)

		p = re.compile(r"[0-9a-zA-Z]+.mp3$")
		filename = p.findall(urlMas[i])
		
		try:
			os.rename(path+"/"+filename[0], path+"/"+artistMas[i]+ " - " + titleMas[i] + ".mp3")
		except:
			print "Невозможно переименовать, оставляю изначальное имя файла!"
	
	print " "
	
print "Задание завершено! Удачи!"

Вот и все. Скрипт был проверен несколько раз, всегда успешно — бэкап делался на 100%, с докачкой и прочим.

Стоит также заметить, что в linux не обязательно класть его туда, где будет создан каталог download, достаточно перейти туда командой cd и запустить скрипт по прямому пути.
cd /data/vkmusic
python /home/zhbert/projects/pufrabvk.py

Как это будет в Windows я не помню, так как давно уже в глаза ее не видел.

Описание и сам файлик лежат тут.

Ну и напоследок скриншот работы срипта:
image

Автор: Zhbert

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js