Introduction
This post continues my series on my ArcaneBooks project. For a background see my post The ArcaneBooks Project – An Introduction.
For this project I am using the OpenLibrary.org website, which provides two web APIs to access book data based on the ISBN. OpenLibrary is sponsored by the InternetArchive.
In a previous post, ArcaneBooks – ISBN Overview, PowerShell, and the Simple OpenLibrary ISBN API, I covered the use of the first API which I nicknamed the Simple API as it is a bit easier to use and dissect the results. I also provided a background on what the ISBN is and how it is formed.
In this post I’ll dive into the more complex of the APIs, what I call the Advance API.
Be aware the use of Simple and Advance are my terms, so I can easily distinguish between the two. They are not terms used by the OpenLibrary.
The Advanced OpenLibrary API
The format of the Advanced API is slightly different from the simple. Here is template.
https://openlibrary.org/api/books?bibkeys=ISBN:[ISBN Goes Here]&jscmd=data&format=json"
You will replace the [ISBN Goes Here]
text with the ISBN number you want to look up. Be aware this can only be digits, you must remove any spaces, dashes, or other characters.
Let’s look at a code example of calling the API and getting all its properties.
Calling The API with PowerShell
First, set an ISBN to lookup. We’ll include some dashes for the demo. The title of the book is "Your HF Digital Companion"
$ISBN = '0-87259-481-5'
Now remove any spaces or dashes, then create the URL.
$isbnFormatted = $ISBN.Replace('-', '').Replace(' ', '')
$baseURL = "https://openlibrary.org/api/books?bibkeys=ISBN:"
$urlParams = "&jscmd=data&format=json"
$url = "$($baseURL)$($isbnFormatted)$($urlParams)"
Now let’s call the URL and put the data into a variable.
$bookData = Invoke-RestMethod $url
If we look at the data held by the variable, we get back a single column. That column holds JSON formatted data. (Note I truncated the XML for readability purposes.)
$bookData
This is the output of displaying the variable.
ISBN:0872594815
---------------
@{url=https://openlibrary.org/books/OL894295M/Your_HF_digital_companion; key=/books/OL894295M; title=Your HF digital companion; authors=System.Object[]; number_of_pages=197; …
We could address the data like:
$bookData.'ISBN:0872594815'.Title
Note we had to wrap the ISBN number in quotes since a colon : isn’t an allowed in property names. However, when we make the call the ISBN isn’t set in stone.
But we do have it in a variable, and we can use string interpolation to format the property.
$bookData."ISBN:$isbnformatted".title
This returns "Your HF digital companion". And yes, the words "digital" and "companion" should normally be capitalized, but this is the way the title comes from OpenLibrary.
Now that we have the formatting for the property name down, we can get the other properties. Note that not all properties that are returned will have data.
$ISBN10 = $bookData."ISBN:$isbnformatted".identifiers.isbn_10
$ISBN13 = $bookData."ISBN:$isbnformatted".identifiers.isbn_13
$Title = $bookData."ISBN:$isbnformatted".title
$LCCN = $bookData."ISBN:$isbnformatted".identifiers.lccn
$NumberOfPages = $bookData."ISBN:$isbnformatted".number_of_pages
$PublishDate = $bookData."ISBN:$isbnformatted".publish_date
$LibraryOfCongressClassification = $bookData."ISBN:$isbnformatted".classifications.lc_classifications
$DeweyDecimalClass = $bookData."ISBN:$isbnformatted".classifications.dewey_decimal_class
$Notes = $bookData."ISBN:$isbnformatted".notes
$CoverUrlSmall = $bookData."ISBN:$isbnformatted".cover.small
$CoverUrlMedium = $bookData."ISBN:$isbnformatted".cover.medium
$CoverUrlLarge = $bookData."ISBN:$isbnformatted".cover.large
The ByStatement sometimes begins with the word "By ". If so we want to remove it. However if we try and do a replace and the by_statement column is null, attempting to call the Replace method will result in an error. So first we have to check for null, and only if the by_statement isn’t null do we attempt to do a replace.
if ($null -eq $bookData."ISBN:$isbnformatted".by_statement)
{ $ByStatement = '' }
else
{ $ByStatement = $bookData."ISBN:$isbnformatted".by_statement.Replace('by ', '') }
For the remaining data, each item can have multiple entries attached. For example, a book could have multiple authors. For our purposes we will just combine into a single entry.
We’ll create a new variable of type StringBuilder, then loop over the list of items in the JSON, combining them into a single string.
In the if
, we check to see if the string already has data, if so we append a comma before adding the second (or more) authors name.
Finally we use the ToString method of the StringBuilder class to convert the value back into a standard string data type.
Books can have multiple authors, as stated each is returned in its own item in an array. This code will combine them into a single string.
Note that when we call the Append method of the StringBuilder class, we need to prepend it with [void]
, otherwise it will send output to the console which we don’t want.
$authors = [System.Text.StringBuilder]::new()
foreach ($a in $bookData."ISBN:$isbnformatted".authors)
{
if ($authors.Length -gt 1)
{ [void]$authors.Append(", $($a.name)") }
else
{ [void]$authors.Append($a.name) }
}
$Author = $authors.ToString()
Subjects can be an array, let’s combine them into a single string.
$subjects = [System.Text.StringBuilder]::new()
foreach ($s in $bookData."ISBN:$isbnformatted".subjects)
{
if ($subjects.Length -gt 1)
{ [void]$subjects.Append(", $($s.name)") }
else
{ [void]$subjects.Append($s.name) }
}
$Subject = $subjects.ToString()
A book could have multiple publishers over time. The author could shift to a new publisher, or more likely a publishing house could be purchases and the new owners name used. The data is returned as an array, so combine them as we did with authors and subjects.
$thePublishers = [System.Text.StringBuilder]::new()
foreach ($p in $bookData."ISBN:$isbnformatted".publishers)
{
if ($thePublishers.Length -gt 1)
{ [void]$thePublishers.Append(", $($p.name)") }
else
{ [void]$thePublishers.Append($p.name) }
}
$Publishers = $thePublishers.ToString()
Since there could be multiple publishers, logically there could be multiple publishing locations. This will combine them into a single string.
$locations = [System.Text.StringBuilder]::new()
foreach ($l in $bookData."ISBN:$isbnformatted".publish_places)
{
if ($locations.Length -gt 1)
{ [void]$locations.Append(", $($l.name)") }
else
{ [void]$locations.Append($l.name) }
}
$PublisherLocation = $locations.ToString()
Now print out all the returned data.
$ISBN10
$ISBN13
$Title
$LCCN
$NumberOfPages
$PublishDate
$LibraryOfCongressClassification
$DeweyDecimalClass
$Notes
$CoverUrlSmall
$CoverUrlMedium
$CoverUrlLarge
$ByStatement
$Author
$Subject
$Publishers
$PublisherLocation
The Output
Here is the output, I put it into a table for easier reading.
Item | Value |
---|---|
ISBN10 | 95185134 |
ISBN13 | [Missing Value] |
Title | Your HF digital companion |
LCCN | [Missing Value] |
Number of Pages | 197 |
Publish Date | 1995 |
LibraryOfCongressClassification | TK5745 .F572 1995 |
DeweyDecimalClass | 004.6/4 |
Notes | Includes bibliographical references. |
Based on | Your RTTY/AMTOR companion. 1st ed. c1993. |
CoverUrlSmall | https://covers.openlibrary.org/b/id/12774631-S.jpg |
CoverUrlMedium | https://covers.openlibrary.org/b/id/12774631-M.jpg |
CoverUrlLarge | https://covers.openlibrary.org/b/id/12774631-L.jpg |
ByStatement | Steve Ford. |
Author | Steve Ford |
Subject | Radiotelegraph, Amateurs’ manuals |
Publishers | American Radio Relay League |
PublisherLocation | Newington, CT |
See Also
The following operators and functions were used or mentioned in this article’s demos. You can learn more about them in some of my previous posts, linked below.
Fun With PowerShell Logic Branching
Fun With PowerShell String Formatting
Conclusion
In this post we saw how to use what I call the advanced API offered by OpenLibrary to retrieve book data based on the ISBN.
In the next post we’ll see how to get book data based on the Library Of Congress Catalog Number, using PowerShell and the Library of Congresses web API.
The demos in this series of blog posts was inspired by my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.
If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight . At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.