Last active
January 15, 2022 18:44
-
-
Save Romern/cd7f1e9a742d27eb3ac104201f6ae87c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
import json | |
import sys | |
import os | |
headers = { | |
'X-Requested-With': 'com.bandcamp.android', | |
'Content-Type': 'application/json', | |
'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9; Unknown Device)', | |
'Host': 'bandcamp.com', | |
} | |
def get_session_cookie(session): | |
data = {"platform":"a","version":191577} | |
return session.post('https://bandcamp.com/api/mobile/24/bootstrap_data', headers=headers, json=data) | |
def fuzzysearch(session, query): | |
params = { | |
"q": query, | |
"param_with_locations": True | |
} | |
return requests.get('https://bandcamp.com/api/fuzzysearch/1/app_autocomplete', headers=headers, params=params) | |
# -fuzzysearch(session, query).json()["results"][0]["id"] | |
def get_discography(session, band_id): | |
data = {"band_id": str(band_id)} | |
return session.post('https://bandcamp.com/api/mobile/24/band_details', headers=headers, json=data) | |
# get_discography(session, "XXXXX").json()["discography"][0]["item_id"] | |
def buy_for_nothing(session, item_id, item_type="album"): | |
data = {"item_id": item_id, "item_type": item_type} | |
return session.post('https://bandcamp.com/api/mobile/24/buy_for_nothing', headers=headers, json=data) | |
# buy_album_for_nothing(session, "XXXXX").json()["downloads"]["flac"]["url"] | |
# if url is not in dict, then it is not buyable for nothing | |
def download_low_quality_stream(session, band_id, item_id, item_type="a"): | |
params = { | |
'band_id': str(band_id), | |
'tralbum_type': item_type, | |
'tralbum_id': str(item_id), | |
} | |
return requests.get('https://bandcamp.com/api/mobile/24/tralbum_details', headers=headers, params=params) | |
# download_low_quality_stream(session, XXXX, XXXXXX).json()["tracks"][0]["streaming_url"]["mp3-128"] | |
def download_file(session, url, filename): | |
with session.get(url, stream=True) as r: | |
r.raise_for_status() | |
with open(filename, 'wb') as f: | |
for chunk in r.iter_content(chunk_size=8192): | |
# If you have chunk encoded response uncomment if | |
# and set chunk_size parameter to None. | |
#if chunk: | |
f.write(chunk) | |
def download_discography(session, bandname, basedir="./"): | |
band_id = fuzzysearch(session, bandname).json()["results"][0]["id"] | |
discography = get_discography(session, band_id) | |
for item in discography.json()["discography"]: | |
item_id = item["item_id"] | |
item_type = item["item_type"] | |
url = buy_for_nothing(session, item["item_id"], item["item_type"]).json()["downloads"].get("flac") | |
if not url: | |
print(f'FLAC not available for item {item["band_name"]} - {item["title"]} ({item["item_type"]})') | |
continue | |
url = url.get("url") | |
base_album_dir = os.path.join(basedir, item["band_name"], item["title"]) | |
os.makedirs(base_album_dir, exist_ok=True) | |
if not url: | |
print(f'Free (high quality) download not available for item {item["band_name"]} - {item["title"]} ({item["item_type"]}), downloading LQ version.') | |
lq = download_low_quality_stream(session, item["band_id"], item["item_id"], item_type="t" if item["item_type"]=="track" else "a").json()["tracks"] | |
# download all tracks | |
for track in lq: | |
outfilename = os.path.join(base_album_dir, f'{track["track_num"]}. {track["title"]}.mp3') | |
#./[outfolder]/[bandname]/[albumname]/[tracknumber]. [trackname].flac | |
print(f'Downloading Track {outfilename}...') | |
download_file(session, track["streaming_url"]["mp3-128"], outfilename) | |
else: | |
# download url | |
outfilename = os.path.join(base_album_dir, 'album.zip') | |
print(f'Downloading Track {outfilename}...') | |
download_file(session, url, outfilename) | |
if __name__ == '__main__': | |
if len(sys.argv)<=2: | |
print(f"{sys.argv[0]} [bandname] [outfolder]\nDownloads the whole discography of a band on bandcamp in FLAC if available.\nFormat: ./[outfolder]/[bandname]/[albumname]/[tracknumber]. [trackname].flac") | |
exit(0) | |
session = requests.Session() | |
download_discography(session, sys.argv[1], sys.argv[2]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment