Skip to content

Instantly share code, notes, and snippets.

@Stephen-ONeil
Created March 17, 2019 04:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Stephen-ONeil/4fadd844450348c0bf3a3a3be71d5c23 to your computer and use it in GitHub Desktop.
Save Stephen-ONeil/4fadd844450348c0bf3a3a3be71d5c23 to your computer and use it in GitHub Desktop.
Morbidly curious about your lifetime total spending on Bandcamp? I was. To get an answer, I wrote some JS that I can run in my browser's dev console to extract that info from Bandcamp's purchase history page.
// Don't go pasting scripts from internet strangers in your dev consoles, ok?
/*
Procudeure (for my own sake, because YOU wouldn't go and paste scripts from a stranger in to your dev console, right?):
1) visit https://bandcamp.com/<username>/purchases
2) run the code under the SETTING UP THE PAGE heading in the dev tool's console
3) run the code under the ACTUALLY SCRAPING heading in the dev tool's console
optional: change "CAD" argument on final line to alternate desired currency code
4) raise your eyebrows at the output (and keep in mind that you're applying current
conversion rates retroactively, and thus getting a skewed result)
This worked on the non-mobile version of Bandcamp's site in February 2019.
*/
//////////// SETTING UP THE PAGE:
// Need all purchase history items loaded before I can scrape them from the browser, lucky for me the
// purchase page's "view all" button:
// a) triggers the same pagination loading as scrolling to the end of the current page does
// b) is hidden, not removed, after the first click
// That means I can load everything WITHOUT repeatedly scrolling the viewport to the bottom of the page
const view_all_button = document.querySelector(".view-all-button");
const load_more_purchase_items = () => view_all_button.click();
const purchase_item_loading_observer = new MutationObserver(load_more_purchase_items);
purchase_item_loading_observer.observe(
document.querySelector(".purchases > ol"),
{
childList: true,
}
);
load_more_purchase_items(); // Kick off loading of the first page of results, the mutation observer will handle the rest
//////////// ACTUALLY SCRAPING:
const payment_node_selector = ".purchases-item-total > div > strong:last-child";
const payment_node_list = document.querySelectorAll(payment_node_selector);
const array_of_payment_nodes = Array.from(payment_node_list);
const payment_data = array_of_payment_nodes.map(
node => {
const payment_text = node.innerText;
// Only looked at the English site. Are currency codes, as displayed to the user, always in the
// English alphabet? I'd assume not, so this is probably not i10n agnostic
const currency_value = parseFloat( payment_text.replace(/[^0-9,\.]/g,"") );
const currency_code = payment_text.replace(/[^A-Z]/g,"");
return {
currency_code,
currency_value
};
}
);
const payment_data_to_converted_total = (payment_data, target_currency_code) => {
const baseline_currency_total = payment_data.reduce(
(total, {currency_code, currency_value}) => total + (currency_value * CurrencyData.rates[currency_code]),
0
);
const target_currency_total = baseline_currency_total / (CurrencyData.rates[target_currency_code]);
return target_currency_total;
};
// Replace "CAD" with currency code of choice (always three letters, always upper case)
payment_data_to_converted_total(payment_data, "CAD")
@Stephen-ONeil
Copy link
Author

Notes:

  • CurrencyData is a global on the Bandcamp site. Handy, I assume they stuck it on window as a dev helper (IMO, boo to using globals in your src, but 👍 to useful dev helpers)
  • Teasing apart their API seemed doable, but less fun. Sharing a script also seemed more interesting to me than trying to write a blog about mucking around trying to speak Bandcamp's REST API
  • ~$1211 CAD, ouch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment