Skip to content

Instantly share code, notes, and snippets.

@lovettbarron
Last active August 8, 2024 15:54
Show Gist options
  • Save lovettbarron/b71c11428a151654474cdb673756319e to your computer and use it in GitHub Desktop.
Save lovettbarron/b71c11428a151654474cdb673756319e to your computer and use it in GitHub Desktop.
Audible Goodreads Importer
# So this is a somewhat manual but not nearly as manual as it could be process.
# First, follow the instructions here: https://www.themodernnomad.com/audible-statistics-extractor/
# Depending on how many pages, copy and paste the results into Excel
# (it will auto format, though you will need to remove the header)
# Before running
# Install the required libraries: pandas and isbntools
# Modify the read_excel argument to point at your file.
# Then point the to_csv argument to wherever you want to export to.
# Go to https://www.goodreads.com/review/import, add the CSV file, and sit back and enjoy
import pandas as pd
from isbntools.app import *
df = pd.read_excel(r'/path/to/the/saved/excel.xlsx')
# Fetch ISBN from title and author using isbn tools
df['isbn'] = df.apply(lambda x : isbn_from_words(x.Title + " " + x.Author), axis=1 )
# Convert Dates
df["Buy Date"] = pd.to_datetime(df["Buy Date"], format="%m-%d-%y", exact=False).dt.strftime('%Y-%m-%d')
#df["Buy Date"] = df["Buy Date"]
# Add to audible
df["Bookshelves"] = "audible"
# Map the Date Read to the Buy Date as a loose proxy
df["Date Read"] = df.apply(lambda x: x["Buy Date"] if x["Time Left"] < 30 else None, axis=1)
# This doesn't actually register, but the export that Goodreads provides is Exclusive Shelf for the read status
df["Exclusive Shelf"] = df.apply(lambda x: "read" if x["Time Left"] < 30 else "currently-reading" if x["Time Left"]/x["Minutes"] < .8 else "to-read", axis=1)
# So I fix it by just appending the status to Bookshelves depending on read status. i.e. if less than 30min left, it's read. If you've listened to more than 20% of it, it's Currently Reading
df["Bookshelves"] = df.apply(lambda x: x["Bookshelves"] + " " + "read" if x["Time Left"] < 30 else x["Bookshelves"] + " " + "currently-reading" if x["Time Left"]/x["Minutes"] < .8 else x["Bookshelves"] + " " + "to-read", axis=1)
# Rename Buy Date to Date Added
df.rename(columns={"Buy Date" : "Date Added"},inplace = True)
df.to_csv(r'/path/to/export/audible-goodreads-import.csv')
print ("Done")
# Audible Library Extractor, minified from from https://www.themodernnomad.com/audible-statistics-extractor/
var includeImage=!1,includeShows=!1,convertToMinutes=function(t){var e=t.match(/.*?(\d+)\s*?h.*?/);return 60*(null!=e?parseInt(e[1]):0)+(null!=(e=t.match(/.*?(\d+)\s*?m.*?/))?parseInt(e[1]):0)},headerRow=[$(document.createTextNode("Title")),$(document.createTextNode("Author")),$(document.createTextNode("Minutes")),$(document.createTextNode("Buy Date")),$(document.createTextNode("Rating")),$(document.createTextNode("Performance")),$(document.createTextNode("Story")),$(document.createTextNode("Time Left"))];includeImage&&headerRow.unshift($(document.createTextNode("Image")));var tableArray=[headerRow],getAuthor=function(t){var e=t.find("td:nth-of-type(3) .bc-list a");if(e.length>1){var n=t.find("td:nth-of-type(3) .bc-list").text().replace(/\s+/g," ").trim(),a="/search?searchAuthor="+encodeURIComponent(n);e=$('<a href="'+a+'">'+n+"</a>")}return e};function tableCreate(t,e){var n=document.createElement("table");n.style.width="70%",n.border="1";for(var a=0;a<e.length;++a)for(var o=n.insertRow(),r=0;r<e[a].length;++r){var d=o.insertCell();e[a][r].each(function(){$(this).clone().appendTo(d)})}t.appendChild(n)}jQuery('tr[class*="adbl-library-row"]').each(function(t){var e=$(this);if(includeShows||"View all episodes"!=e.find("td:nth-of-type(2) .bc-list-item:nth-of-type(2)").text().trim()){var n=e.find("td:nth-of-type(1) img").clone().attr("width","90"),a=[e.find("td:nth-of-type(2) .bc-list-item:nth-of-type(1)").contents(),getAuthor(e),$(document.createTextNode(convertToMinutes(e.find("td:nth-of-type(4)").text()))),$(document.createTextNode(e.find("td:nth-of-type(5)").text())),$(document.createTextNode(e.find("*[data-star-count]:first").attr("data-star-count"))),$(document.createTextNode(e.find("*[data-star-count]:eq(1)").attr("data-star-count"))),$(document.createTextNode(e.find("*[data-star-count]:eq(2)").attr("data-star-count"))),$(document.createTextNode(convertToMinutes(e.find("td:nth-of-type(1) .bc-col:nth-of-type(1) .bc-row:nth-of-type(3) ").text().trim().split("\n")[0])))];includeImage&&a.unshift(n),tableArray.push(a)}}),tableCreate($("body").empty()[0],tableArray);
@lovettbarron
Copy link
Author

@donoftime Er, two years too late, but awesome work! :)

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