ArcaneBooks – PowerShell and the Advanced OpenLibrary ISBN API

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 Loops

Fun With PowerShell Strings

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.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s