Пользователь
0,1
рейтинг
15 мая 2012 в 10:24

Разработка → Делаем бэкап музыкальной базы vkontakte с помощью 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
карма
12,0
рейтинг 0,1
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (43)

  • НЛО прилетело и опубликовало эту надпись здесь
    • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      а еще в урл дисклоусится айдишник автора скрипта, а там уже и до его смешных фоток не далеко :)

      • 0
        Черт, спалился =)
    • 0
      Мое больное воображение решило, что с вгетом оно красивше будет. Да и какая разница, если вгет все равно по-умолчанию в системе есть?
  • +30
    Слишком много странных комментариев, которые веселят только автора.
    • +3
      Ещё автор напутал с принтами. Гораздо интереснее бы смотрелось так:
      print("Ну")
      print("вот,")
      print("теперь")
      print("приступаем")
      print("к")
      print("даунлоадингу!")
      print("Помни,")
      print("юзер,")
      print("что")
      print("скачается")
      print("весь")
      print("плейлист!\n")
      
      • +1
        пробелы все-таки нужны :)
        • 0
          \n print() ставит автоматом.
  • +24
    Судя по тексту в коде автор тот еще остряк
  • +1
    Скрипт можно смело ужать на пару килобайт, выдрав бессмысленный текст.
    • +1
      Ещё один что-ли? Не так давно такой же точно с пхп был.
      А если ближе к делу:
      >Ведь опыт использования у меня уже есть (писал десктопный плеер на Qt). Но лепить полноценное приложение, тем более на плюсах или каком-либо другом языке, мне показалось слегка не умным решением.
      >писал десктопный плеер на Qt
      Ты конечно извини, но зачем лепить полноценное приложение, когда оно по твоим словам уже слеплено? Как на счет того, чтобы поставить просто какую-нибудь галку, тычку, чтобы вместо воспроизведения, твоя чудо машина треки складировала в папку? Или ещё такой вариант, чтобы воспроизводящийся трек она сейвила в заранее выбранную папку. Ну и уж напоследок, совсем идеальный вариант: те треки которые тебе сильно по нраву, ты «отмечаешь» либо 5-звездочным рейтингом, либо каким-нибудь хоткеем, и они автоматически сохраняются в заданную папку.
      Господи, столько всяких разных вариантов, и любой из них дописался бы в существующий плеер на Qt раза в два быстрее чем сочинение этих твоих юмористических отступлений в скрипте.
      • 0
        Упс. Немножко не туда отправил, не обессудьте. Хотел в основной тред отправить, а не в комментарий комментарию :}
      • 0
        Да, ты прав. Но тот проект я не трогал уже, наверное, с год, и вспоминать, что там да как мне было совершенно влом.
  • +8
    Одному мне показалось, что комментариев больше, чем кода? :)
    • –5
      Типичная ситуация для Python…
  • 0
    Похоже, нужен python 2.7, в 3.3 ругается на строки типа print «Привет, юзер!» (надо print («Привет, юзер!»)), нет urllib2 (надо urllib.request), raw_input (надо input), и прочая…
  • 0
    Ээх… лучше бы в десктопный клиент свой добавили функцию скачать все…
  • 0
    Кстати, токен для авторизации можно один раз получить и вбить в скрипт, чтоб не париться с копипастом каждый раз. Для этого нужно запросить приложению разрешения для работы в оффлайне
  • +2
    А теперь тоже самое в пять строк на баше?
  • +1
    похоже автору стоит почитать Дзен питона
    import this
    
  • 0
    А я недавно делал парсер Яндексовых плейлистов, тоже на Python. Надо было сохранить парочку для оффлайнового доступа. Музыка вообще не нужна была, нужны были только метаданные (исполнитель, название, альбом).

    Скажи, Яндекс, ну вот что, нельзя сделать экспорт плейлистов хоть в txt?
    • 0
      Можете показать, выложить? Часто пользуюсь яндекс музыкой но при перенесении музыки в оффлайн все время руками копирую названия композиций, все руки не доходят сделать скрипт. Очень вовремя вы здесь появились. Буду благодарен, если поделитесь вашими наработками.
      • –1
        На выходных тогда выложу, сейчас работы привалило :)
        • 0
          Написать скрипт?
  • 0
    Скрипт похож на сценарий для визуальной новеллы на языке renpy.org
  • +4
    берем файрфокс (!), открываем нужный плейлист, сейвим как text file, далее SED > GREP > WGET
    и никаких удавов
  • 0
    «Итак, первое, что я сделал — октрыл список расширений оперы и набрал в поиске «vkontakte». Но вот оказия, все приложения предлагали качать по одному треку, в основном добавляя рядом с ним кнопочку «скачать». „

    Ммм. Видимо плохо смотрели. Расширение SaveFrom.net помощник позволяет скачивать всю музыку со страницы.
  • 0
    Спасибо. Нашел недоработку. У меня в именах файлов
    &
    вместо
    &
    . Думаю аналогично с другими спецсимволами html.
    • 0
      Эх злобный парсер. Ну вы поняли)
  • 0
    filename_new = path+"/"+artistMas[i]+ " - " + titleMas[i] + ".mp3";
    ...
    os.rename(path+"/"+filename[0], path+"/"+artistMas[i]+ " - " + titleMas[i] + ".mp3")
    


    Пути корректно делать через os.path.join()
  • 0
    Надстройка VKOpt позволяет получить полный список ссылок на mp3-файлы из плей-листа одним кликом.
    image
    Копирование списка открывает окно Download Master, который быстро скачает всё в нужную папку. Зачем, простите, столько велосипедов?
    • 0
      Не у всех людей на компе стоит винда. Стало быть, не у всех стоит даунлоад мастер.

      Плюс, просто по ссылке он скачат все с названиями в виде dkjghlaisduhjkashlfha.mp3, а не с нормальными.
      • 0
        Даже на мобильных платформах есть менеджеры загрузок, что поддерживают закачку по списку.
        По ссылке вида dkjghlaisduhjkashlfha.mp3/?Band%20-%20Song.mp3 скачается с нормальным названием. VKopt, как и другие подобные скрипты, выдают линки именно в удобоваримом виде.
        Ещё аргументы?
        • 0
          На Mac'e с скачкой по списку справилась бесплатная Progressive Downloader 1.4 www.macpsd.net
  • 0
    А я вот искал способ автоматизации скачки видео определённого юзера ВК. Наткнулся на эту статью. Только вот не могу разобраться как качать видео таким манером…
  • 0
    А мне вот очень пригодится скриптик ваш, ибо винду тоже редко вижу :)
    И немного весёлых комментариев, контрастирующих с серой массой остальных очень даже в кассу =)
    Я бы вот ещё только на github бы закоммитил скрипт, чтобы не пропал он и гуглился лучше.
    Спасибо!

    ps. баг с & удалось пофиксить?
  • 0
    Перезалейте пожалуйста код.
    • 0
      Я только начал изучать python и попробывал сделать «что-то» используя преведенные куски кода плюс добавил курл для того чтобы не приходилось в ручную вбивать. Если пригодится, используйте на здоровье.
      pastebin link

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.