Last active
August 8, 2024 15:54
-
-
Save lovettbarron/b71c11428a151654474cdb673756319e to your computer and use it in GitHub Desktop.
Audible Goodreads Importer
This file contains 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
# 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") |
This file contains 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
# 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); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@donoftime Er, two years too late, but awesome work! :)