Skip to content

Instantly share code, notes, and snippets.

@Rubikoid
Forked from st4lk/vkcom_audio_download.py
Last active May 26, 2017 09:39
Show Gist options
  • Select an option

  • Save Rubikoid/8a108f8882f57ef566935be571a5a25e to your computer and use it in GitHub Desktop.

Select an option

Save Rubikoid/8a108f8882f57ef566935be571a5a25e to your computer and use it in GitHub Desktop.
Python: vkontakte.ru (vk.com) audio music downloader
# -*- coding: utf-8 -*-
"""
Скрипт для скачивания музыки с сайта vk.com
Запуск:
python vk_dwn.py
Принцип работы:
Скрипт проверяет сохраненный access_token. Если его нет,
то происходит запрос данных и авторизация.
Далее будут скачиваться все ваши аудиозаписи. Если аудиозапись уже есть на
диске - то скачивания не происходит.
current_client_id/current_client_secret - актуальные client_id/secret для прямой авторизации VK
"""
from robobrowser import RoboBrowser
import pickle
import json
import urllib
import urllib2
import HTMLParser
import re
import os
import sys
import urlparse
current_client_id = '5027722'
current_client_secret = 'Skg1Tn1r2qEbbZIAJMx3'
# if None, then save mp3 in current folder
MUSIC_FOLDER = 'vk_music'
# file, where auth data is saved
AUTH_FILE = '~/.config/.vk_auth_data'
# chars to exclude from filename
FORBIDDEN_CHARS = '/\\\?%*:|"<>!'
class VKUrlOpener(urllib.FancyURLopener):
version = 'VKAndroidApp/4.9-1118'
urllib._urlopener = VKUrlOpener()
def get_saved_auth_params():
access_token = None
user_id = None
try:
with open(AUTH_FILE, 'rb') as pkl_file:
access_token = pickle.load(pkl_file)
user_id = pickle.load(pkl_file)
except IOError:
pass
return access_token, user_id
def save_auth_params(access_token, user_id):
with open(AUTH_FILE, 'wb') as output:
pickle.dump(access_token, output)
pickle.dump(user_id, output)
os.chmod(AUTH_FILE, 700)
def get_auth_params():
login = raw_input("Your login:")
password = raw_input("Your password:")
auth_url = ("https://oauth.vk.com/token?grant_type=password&client_id={cli_id}&client_secret={cli_sec}"
"&username={login}&password={password}".format(cli_id=current_client_id,cli_sec=current_client_secret,login=login, password=password))
browser = RoboBrowser(history=True)
browser.open(auth_url)
if 'error' in browser.response.text:
if '2fa_app' in browser.response.text:
redirect_url = json.loads(str(browser.response.text))["redirect_uri"]
browser.open(redirect_url)
twoFA = raw_input("2factor need, code:")
form = browser.get_form()
form['code'] = twoFA
browser.submit_form(form)
if 'success=1' in browser.response.url:
redirected_url = browser.response.url
else:
print browser.parsed
sys.exit()
aup = urlparse.parse_qs(redirected_url)
save_auth_params(aup['access_token'][0], aup['user_id'][0])
return aup['access_token'][0], aup['user_id'][0]
def get_tracks_metadata(access_token, user_id):
url = ("https://api.vk.com/method/audio.get?"
"uid={uid}&access_token={atoken}&v=5.60".format(
uid=user_id, atoken=access_token))
req = urllib2.Request(url, headers={ 'User-Agent': 'VKAndroidApp/4.9-1118'})
audio_get_page = urllib2.urlopen(req).read()
return json.loads(audio_get_page)['response']["items"]
def get_track_full_name(t_data):
html_parser = HTMLParser.HTMLParser()
full_name = u"{0}_{1}".format(
html_parser.unescape(t_data['artist'][:100]).strip(),
html_parser.unescape(t_data['title'][:100]).strip(),
)
full_name = re.sub('[' + FORBIDDEN_CHARS + ']', "", full_name)
full_name = re.sub(' +', ' ', full_name)
return full_name + ".mp3"
def download_track(t_url, t_name):
t_path = os.path.join(MUSIC_FOLDER or "", t_name)
if not os.path.exists(t_path):
print "Downloading {0}".format(t_name.encode('ascii', 'replace'))
urllib.urlretrieve(t_url, t_path)
def getTracks():
access_token, user_id = get_saved_auth_params()
if not access_token or not user_id:
access_token, user_id = get_auth_params()
tracks = get_tracks_metadata(access_token, user_id)
if MUSIC_FOLDER and not os.path.exists(MUSIC_FOLDER):
os.makedirs(MUSIC_FOLDER)
for t in tracks:
t_name = get_track_full_name(t)
download_track(t['url'], t_name)
print "All music is up to date"
return tracks
def main():
tracks = getTracks()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment