Skip to content

Instantly share code, notes, and snippets.

@potat-dev
Created January 8, 2023 01:41
Show Gist options
  • Save potat-dev/0d31fed785b32edc4c5afa872a212fce to your computer and use it in GitHub Desktop.
Save potat-dev/0d31fed785b32edc4c5afa872a212fce to your computer and use it in GitHub Desktop.
This code is a snippet from my project, which downloads music from Yandex.Music
from tqdm import tqdm
import os
import requests
import pprint
import hashlib
import base64
# for xml parsing
import xml.etree.ElementTree as ET
track_url = 'https://music.yandex.ru/album/18903866/track/87442509'
token = '' # AQAAAAAu
# how to get token:
# https://github.com/MarshalX/yandex-music-api/discussions/513#discussioncomment-2729781
track_id = track_url.split('/')[-1] # get track id from url
url = f"https://api.music.yandex.net/tracks/{track_id}/download-info"
headers = {
'Authorization': f'OAuth {token}',
}
session = requests.Session()
response = session.request("GET", url, headers=headers).json()
if 'result' in response:
result = filter(lambda i: i['codec'] == "mp3", response['result'])
best = max(result, key=lambda i: i['bitrateInKbps']) # get best quality
url = best['downloadInfoUrl']
else:
print('error')
exit()
def parseTrackDownloadInfoXML(path):
xml = session.get(path)
if '401 Authorization Required' in xml.text:
print('auth error')
return False
root = ET.fromstring(xml.text)
host = root.find('host').text
path = root.find('path').text
ts = root.find('ts').text
s = root.find('s').text
# get sign variable as follows:
# https://github.com/kontsevoye/ym-api/blob/d74fc2c23007f03f0aaff03d14cae8c50d0919e7/src/YMApi.ts#L423-L437
sign = 'XGRlBW9FXlekgbPrRHuSiA' + path[1:] + s
sign = hashlib.md5(sign.encode('utf-8')).hexdigest()
return f'https://{host}/get-mp3/{sign}/{ts}{path}'
def download(url, filename):
r = session.get(url, stream=True)
total_length = int(r.headers.get('content-length'))
with open(filename, 'wb') as f:
for chunk in tqdm(r.iter_content(chunk_size=1024), total=total_length/1024, unit='KB'):
if chunk:
f.write(chunk)
f.flush()
url = parseTrackDownloadInfoXML(url)
if url:
print(url)
download(url, 'test.mp3')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment