In [2]:
!pip install pandas
Requirement already satisfied: pandas in /home/jchen/miniconda3/lib/python3.11/site-packages (2.1.4) Requirement already satisfied: numpy<2,>=1.23.2 in /home/jchen/miniconda3/lib/python3.11/site-packages (from pandas) (1.26.2) Requirement already satisfied: python-dateutil>=2.8.2 in /home/jchen/miniconda3/lib/python3.11/site-packages (from pandas) (2.8.2) Requirement already satisfied: pytz>=2020.1 in /home/jchen/miniconda3/lib/python3.11/site-packages (from pandas) (2023.3.post1) Requirement already satisfied: tzdata>=2022.1 in /home/jchen/miniconda3/lib/python3.11/site-packages (from pandas) (2023.4) Requirement already satisfied: six>=1.5 in /home/jchen/miniconda3/lib/python3.11/site-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)
In [3]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
In [4]:
data_location = "book1-100k.csv"
df = pd.read_csv(data_location)
print(len(df))
df.head()
58292
Out[4]:
| Id | Name | RatingDist1 | pagesNumber | RatingDist4 | RatingDistTotal | PublishMonth | PublishDay | Publisher | CountsOfReview | PublishYear | Language | Authors | Rating | RatingDist2 | RatingDist5 | ISBN | RatingDist3 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | Harry Potter and the Half-Blood Prince (Harry ... | 1:9896 | 652 | 4:556485 | total:2298124 | 16 | 9 | Scholastic Inc. | 28062 | 2006 | eng | J.K. Rowling | 4.57 | 2:25317 | 5:1546466 | NaN | 3:159960 |
| 1 | 2 | Harry Potter and the Order of the Phoenix (Har... | 1:12455 | 870 | 4:604283 | total:2358637 | 1 | 9 | Scholastic Inc. | 29770 | 2004 | eng | J.K. Rowling | 4.50 | 2:37005 | 5:1493113 | 0439358078 | 3:211781 |
| 2 | 3 | Harry Potter and the Sorcerer's Stone (Harry P... | 1:108202 | 309 | 4:1513191 | total:6587388 | 1 | 11 | Scholastic Inc | 75911 | 2003 | eng | J.K. Rowling | 4.47 | 2:130310 | 5:4268227 | NaN | 3:567458 |
| 3 | 4 | Harry Potter and the Chamber of Secrets (Harry... | 1:11896 | 352 | 4:706082 | total:2560657 | 1 | 11 | Scholastic | 244 | 2003 | eng | J.K. Rowling | 4.42 | 2:49353 | 5:1504505 | 0439554896 | 3:288821 |
| 4 | 5 | Harry Potter and the Prisoner of Azkaban (Harr... | 1:10128 | 435 | 4:630534 | total:2610317 | 1 | 5 | Scholastic Inc. | 37093 | 2004 | eng | J.K. Rowling | 4.57 | 2:24849 | 5:1749958 | 043965548X | 3:194848 |
In [5]:
eng = df[df['Language'] == 'eng']
ratings = (eng.groupby('Authors'))['Rating'].mean().reset_index()
ratings.sort_values('Rating', ascending = False)
mydata = df[['Id','pagesNumber']]
print(mydata.head())
earlyratings = ratings[0:10]
earlyratings
Id pagesNumber 0 1 652 1 2 870 2 3 309 3 4 352 4 5 435
Out[5]:
| Authors | Rating | |
|---|---|---|
| 0 | A.A. Milne | 4.356 |
| 1 | A.D.P. Briggs | 3.760 |
| 2 | A.E. Cunningham | 4.150 |
| 3 | A.J. Frost | 3.840 |
| 4 | A.J. Jacobs | 3.760 |
| 5 | A.J. Mackinnon | 4.240 |
| 6 | A.J.P. Taylor | 4.000 |
| 7 | A.L. Singer | 4.070 |
| 8 | A.M. Homes | 3.600 |
| 9 | A.N. Roquelaure | 3.735 |
In [6]:
plt.style.use('_mpl-gallery')
# make the data
# plot
fig, ax = plt.subplots()
ax.scatter(mydata['Id'], mydata['pagesNumber'])
plt.show()
In [7]:
plt.hist(earlyratings['Rating'], bins=10, alpha=0.45, color='Blue')
plt.title("histogram showing ratings")
plt.legend(["book rating"])
plt.xlabel("rating")
plt.ylabel("count")
plt.show()
In [8]:
bookdata = eng[['Authors', 'PublishYear', 'Rating', 'CountsOfReview', 'Name']]
bookdata.describe
Out[8]:
<bound method NDFrame.describe of Authors PublishYear Rating CountsOfReview \
0 J.K. Rowling 2006 4.57 28062
1 J.K. Rowling 2004 4.50 29770
2 J.K. Rowling 2003 4.47 75911
3 J.K. Rowling 2003 4.42 244
4 J.K. Rowling 2004 4.57 37093
... ... ... ... ...
58260 Harvey J. Kaye 2006 3.91 31
58262 Thomas Paine 2005 3.91 2
58265 John McCain 2000 3.86 288
58280 Robert Silverberg 2002 3.48 0
58281 Robert Silverberg 2001 3.82 5
Name
0 Harry Potter and the Half-Blood Prince (Harry ...
1 Harry Potter and the Order of the Phoenix (Har...
2 Harry Potter and the Sorcerer's Stone (Harry P...
3 Harry Potter and the Chamber of Secrets (Harry...
4 Harry Potter and the Prisoner of Azkaban (Harr...
... ...
58260 Thomas Paine and the Promise of America (Oxfor...
58262 Common Sense and Other Writings
58265 Faith of My Fathers: A Family Memoir
58280 Science Fiction: The Best of 2001
58281 Nebula Awards Showcase 2001
[15988 rows x 5 columns]>
In [9]:
review_author = bookdata.groupby(['Authors'])
review_author.head()
rate_author = review_author[['Rating']].mean().reset_index()
rate_author.sort_values(by = 'Authors', ascending = True)
Out[9]:
| Authors | Rating | |
|---|---|---|
| 0 | A.A. Milne | 4.356000 |
| 1 | A.D.P. Briggs | 3.760000 |
| 2 | A.E. Cunningham | 4.150000 |
| 3 | A.J. Frost | 3.840000 |
| 4 | A.J. Jacobs | 3.760000 |
| ... | ... | ... |
| 6943 | testing testing | 3.950000 |
| 6944 | Álvaro Mutis | 4.330000 |
| 6945 | Émile Zola | 3.948182 |
| 6946 | ابن كثير | 4.140000 |
| 6947 | غلامحسین ساعدی | 3.870000 |
6948 rows × 2 columns
In [10]:
names = rate_author['Authors'][0:20]
values = rate_author['Rating'][0:20]
fig, axs = plt.subplots(1, 3, figsize=(100, 20), sharey=True)
axs[0].bar(names, values)
axs[1].scatter(names, values)
axs[2].plot(names, values)
fig.suptitle('Categorical Plotting')
Out[10]:
Text(0.5, 0.98, 'Categorical Plotting')
In [16]:
popular_books = df[df['CountsOfReview'] > 1000]
popular_books.shape
Out[16]:
(1491, 18)
In [19]:
top_hundred = popular_books.sort_values('Rating', ascending = False).iloc[:100]
top_hundred
#get the title of the top hundred books with more than 1000 reviews
Out[19]:
| Id | Name | RatingDist1 | pagesNumber | RatingDist4 | RatingDistTotal | PublishMonth | PublishDay | Publisher | CountsOfReview | PublishYear | Language | Authors | Rating | RatingDist2 | RatingDist5 | ISBN | RatingDist3 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 22 | 30 | J.R.R. Tolkien 4-Book Boxed Set: The Hobbit an... | 1:920 | 1728 | 4:22283 | total:106621 | 25 | 9 | Ballantine Books | 1548 | 2012 | eng | J.R.R. Tolkien | 4.60 | 2:1443 | 5:75533 | 0345538374 | 3:6442 |
| 0 | 1 | Harry Potter and the Half-Blood Prince (Harry ... | 1:9896 | 652 | 4:556485 | total:2298124 | 16 | 9 | Scholastic Inc. | 28062 | 2006 | eng | J.K. Rowling | 4.57 | 2:25317 | 5:1546466 | NaN | 3:159960 |
| 4 | 5 | Harry Potter and the Prisoner of Azkaban (Harr... | 1:10128 | 435 | 4:630534 | total:2610317 | 1 | 5 | Scholastic Inc. | 37093 | 2004 | eng | J.K. Rowling | 4.57 | 2:24849 | 5:1749958 | 043965548X | 3:194848 |
| 54174 | 93124 | Harry Potter and the Half-Blood Prince (Harry ... | 1:9938 | 607 | 4:558101 | total:2306655 | 16 | 7 | Bloomsbury Publishing | 1142 | 2005 | eng | J.K. Rowling | 4.57 | 2:25375 | 5:1552880 | 0747581088 | 3:160361 |
| 5 | 6 | Harry Potter and the Goblet of Fire (Harry Pot... | 1:9419 | 734 | 4:606800 | total:2431085 | 28 | 9 | Scholastic | 31978 | 2002 | eng | J.K. Rowling | 4.56 | 2:24282 | 5:1612165 | NaN | 3:178419 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 20696 | 34501 | A Hat Full of Sky (Discworld, #32; Tiffany Ach... | 1:398 | 352 | 4:21039 | total:59958 | 5 | 5 | Corgi Childrens | 1306 | 2005 | eng | Terry Pratchett | 4.30 | 2:1225 | 5:29603 | 055255264X | 3:7693 |
| 13566 | 22917 | The Complete Grimm's Fairy Tales | 1:961 | 880 | 4:45258 | total:140652 | 12 | 9 | Pantheon Books | 1335 | 1976 | eng | Jacob Grimm | 4.30 | 2:2883 | 5:71185 | NaN | 3:20365 |
| 8714 | 14383 | No Rest for the Wicked (Immortals After Dark, #2) | 1:294 | 356 | 4:16463 | total:49812 | 31 | 10 | Pocket Star | 1320 | 2006 | eng | Kresley Cole | 4.30 | 2:1197 | 5:24993 | NaN | 3:6865 |
| 7681 | 12657 | The Source | 1:364 | 1080 | 4:11786 | total:37855 | 9 | 7 | Random House, Inc. | 1159 | 2002 | eng | James A. Michener | 4.30 | 2:1046 | 5:19647 | 0375760385 | 3:5012 |
| 10405 | 17267 | The Great Divorce | 1:1649 | 160 | 4:31811 | total:102441 | 1 | 2 | HarperCollins | 3881 | 2002 | eng | C.S. Lewis | 4.29 | 2:3060 | 5:53138 | 0006280560 | 3:12783 |
100 rows × 18 columns
In [57]:
top_publishers = top_hundred.groupby(['Publisher'])['Name'].size().reset_index()
top_publishers.sort_values('Name', ascending = False)
Out[57]:
| Publisher | Name | |
|---|---|---|
| 7 | Bantam | 6 |
| 51 | Roc | 5 |
| 54 | Scholastic Inc. | 3 |
| 68 | Vintage | 3 |
| 18 | Delta | 3 |
| ... | ... | ... |
| 32 | Houghton Mifflin Harcourt | 1 |
| 34 | Knopf | 1 |
| 1 | Alfred A. Knopf | 1 |
| 36 | NAL | 1 |
| 70 | Yale University Press | 1 |
71 rows × 2 columns
In [54]:
toptop = top_publishers[top_publishers['Name'] > 2]
toptop #find publishers with most books in top ratings
Out[54]:
| Publisher | Name | |
|---|---|---|
| 7 | Bantam | 6 |
| 18 | Delta | 3 |
| 51 | Roc | 5 |
| 54 | Scholastic Inc. | 3 |
| 65 | Tor Books | 3 |
| 68 | Vintage | 3 |
In [131]:
#try to get publishers, number of books each publisher has but also its name and rating
#publisher_list = top_hundred['Name'].groupby(['Publisher'])
publisher_list = top_hundred[['Publisher', 'Rating', 'Name']].groupby(['Publisher']).size().reset_index(name='Number_of_Items')
"""publisher_counts = top_hundred.groupby('Publisher').agg(
Rating=('Rating', 'mean'), # Calculate the mean rating for each publisher
Title_Count=('Name', 'size'), # Count the number of titles for each publisher
Number_of_Items=('Name', 'count') # Count the total number of items for each publisher
).reset_index()
publisher_counts"""
top_few = publisher_list[publisher_list['Number_of_Items'] > 2]
In [132]:
names = top_few['Publisher']
values = top_few['Number_of_Items']
fig, axs = plt.subplots(1, 3, figsize=(100, 20), sharey=True)
axs[0].bar(names, values)
axs[1].scatter(names, values)
axs[2].plot(names, values)
fig.suptitle('Categorical Plotting')
Out[132]:
Text(0.5, 0.98, 'Categorical Plotting')
In [125]:
fig = plt.figure(figsize = (10, 5))
plt.bar(names,values, color = 'maroon', width = 0.4)
plt.xlabel("Publisher")
plt.ylabel("Number of books")
plt.title("Number of books in top 100 rated books by publisher")
plt.show()
trying to get book covers¶
After looking through data and trying to get the top 100 books, I will try to use their isbns to get the book cover urls so that I can render the book images and publish it online
In [127]:
!pip install isbnlib
import isbnlib
Collecting isbnlib Downloading isbnlib-3.10.14-py2.py3-none-any.whl.metadata (16 kB) Downloading isbnlib-3.10.14-py2.py3-none-any.whl (52 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 52.5/52.5 kB 907.5 kB/s eta 0:00:000:00:01 Installing collected packages: isbnlib Successfully installed isbnlib-3.10.14
In [133]:
top_hundred
Out[133]:
| Id | Name | RatingDist1 | pagesNumber | RatingDist4 | RatingDistTotal | PublishMonth | PublishDay | Publisher | CountsOfReview | PublishYear | Language | Authors | Rating | RatingDist2 | RatingDist5 | ISBN | RatingDist3 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 22 | 30 | J.R.R. Tolkien 4-Book Boxed Set: The Hobbit an... | 1:920 | 1728 | 4:22283 | total:106621 | 25 | 9 | Ballantine Books | 1548 | 2012 | eng | J.R.R. Tolkien | 4.60 | 2:1443 | 5:75533 | 0345538374 | 3:6442 |
| 0 | 1 | Harry Potter and the Half-Blood Prince (Harry ... | 1:9896 | 652 | 4:556485 | total:2298124 | 16 | 9 | Scholastic Inc. | 28062 | 2006 | eng | J.K. Rowling | 4.57 | 2:25317 | 5:1546466 | NaN | 3:159960 |
| 4 | 5 | Harry Potter and the Prisoner of Azkaban (Harr... | 1:10128 | 435 | 4:630534 | total:2610317 | 1 | 5 | Scholastic Inc. | 37093 | 2004 | eng | J.K. Rowling | 4.57 | 2:24849 | 5:1749958 | 043965548X | 3:194848 |
| 54174 | 93124 | Harry Potter and the Half-Blood Prince (Harry ... | 1:9938 | 607 | 4:558101 | total:2306655 | 16 | 7 | Bloomsbury Publishing | 1142 | 2005 | eng | J.K. Rowling | 4.57 | 2:25375 | 5:1552880 | 0747581088 | 3:160361 |
| 5 | 6 | Harry Potter and the Goblet of Fire (Harry Pot... | 1:9419 | 734 | 4:606800 | total:2431085 | 28 | 9 | Scholastic | 31978 | 2002 | eng | J.K. Rowling | 4.56 | 2:24282 | 5:1612165 | NaN | 3:178419 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 20696 | 34501 | A Hat Full of Sky (Discworld, #32; Tiffany Ach... | 1:398 | 352 | 4:21039 | total:59958 | 5 | 5 | Corgi Childrens | 1306 | 2005 | eng | Terry Pratchett | 4.30 | 2:1225 | 5:29603 | 055255264X | 3:7693 |
| 13566 | 22917 | The Complete Grimm's Fairy Tales | 1:961 | 880 | 4:45258 | total:140652 | 12 | 9 | Pantheon Books | 1335 | 1976 | eng | Jacob Grimm | 4.30 | 2:2883 | 5:71185 | NaN | 3:20365 |
| 8714 | 14383 | No Rest for the Wicked (Immortals After Dark, #2) | 1:294 | 356 | 4:16463 | total:49812 | 31 | 10 | Pocket Star | 1320 | 2006 | eng | Kresley Cole | 4.30 | 2:1197 | 5:24993 | NaN | 3:6865 |
| 7681 | 12657 | The Source | 1:364 | 1080 | 4:11786 | total:37855 | 9 | 7 | Random House, Inc. | 1159 | 2002 | eng | James A. Michener | 4.30 | 2:1046 | 5:19647 | 0375760385 | 3:5012 |
| 10405 | 17267 | The Great Divorce | 1:1649 | 160 | 4:31811 | total:102441 | 1 | 2 | HarperCollins | 3881 | 2002 | eng | C.S. Lewis | 4.29 | 2:3060 | 5:53138 | 0006280560 | 3:12783 |
100 rows × 18 columns
In [150]:
def get_book_cover_isbnlib(isbn):
cover_url = isbnlib.cover(isbn)
return cover_url
cover_urls = []
In [140]:
#for index, row in top_hundred.iterrows():
# cover_urls.append(get_book_cover_isbnlib(row['ISBN']))
#not every row has an ISBN
Trying with google api book titles instead
In [156]:
import requests
def get_book_cover(title=None, isbn=None):
if title:
url = f'https://www.googleapis.com/books/v1/volumes?q=intitle:{title}&maxResults=1'
elif isbn:
url = f'https://www.googleapis.com/books/v1/volumes?q=isbn:{isbn}&maxResults=1'
else:
return None
response = requests.get(url)
if response.status_code == 200:
data = response.json()
if 'items' in data and data['items']:
volume_info = data['items'][0].get('volumeInfo', {})
image_links = volume_info.get('imageLinks', {})
thumbnail_url = image_links.get('thumbnail')
return thumbnail_url
return None
# Example usage
book_cover_url = get_book_cover(title='The Great Gatsby')
print(book_cover_url)
covers = []
http://books.google.com/books/content?id=iXn5U2IzVH0C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api
In [154]:
for index, row in top_hundred.iterrows():
cover_urls.append({'title': row['Name'], 'cover': get_book_cover(row['Name'], row['ISBN'])})
In [155]:
cover_urls
Out[155]:
[{'title': 'J.R.R. Tolkien 4-Book Boxed Set: The Hobbit and The Lord of the Rings',
'cover': 'http://books.google.com/books/content?id=XBaNEAAAQBAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'Harry Potter and the Half-Blood Prince (Harry Potter, #6)',
'cover': 'http://books.google.com/books/content?id=R7YsowJI9-IC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Harry Potter and the Prisoner of Azkaban (Harry Potter, #3)',
'cover': 'http://books.google.com/books/content?id=Sm5AKLXKxHgC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Harry Potter and the Half-Blood Prince (Harry Potter, #6)',
'cover': 'http://books.google.com/books/content?id=R7YsowJI9-IC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Harry Potter and the Goblet of Fire (Harry Potter, #4)',
'cover': 'http://books.google.com/books/content?id=etukl7GfrxQC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Complete Maus',
'cover': 'http://books.google.com/books/content?id=ASajL1zsziAC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Season of Mists (The Sandman, #4)', 'cover': None},
{'title': 'The Darkest Hour (Warriors, #6)',
'cover': 'http://books.google.com/books/content?id=HuLlF0isUAEC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Power Broker: Robert Moses and the Fall of New York',
'cover': 'http://books.google.com/books/content?id=r9WMDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Harry Potter and the Order of the Phoenix (Harry Potter, #5)',
'cover': 'http://books.google.com/books/content?id=zpvysRGsBlwC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Fullmetal Alchemist, Vol. 1 (Fullmetal Alchemist, #1)',
'cover': 'http://books.google.com/books/content?id=zqw8AwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Harry Potter and the Order of the Phoenix (Harry Potter, #5)',
'cover': 'http://books.google.com/books/content?id=zpvysRGsBlwC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "Harry Potter and the Sorcerer's Stone",
'cover': 'http://books.google.com/books/content?id=wrOQLV6xB-wC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "Harry Potter and the Sorcerer's Stone (Harry Potter, #1)",
'cover': 'http://books.google.com/books/content?id=wrOQLV6xB-wC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'You Are Special (Wemmicksville, #1)',
'cover': 'http://books.google.com/books/content?id=CayRPwAACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'Lover Awakened (Black Dagger Brotherhood, #3)',
'cover': 'http://books.google.com/books/content?id=yziKDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Final Empire (Mistborn, #1)',
'cover': 'http://books.google.com/books/content?id=t_ZYYXZq4RgC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Monster at the End of this Book',
'cover': 'http://books.google.com/books/content?id=rI0pEAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'A Breath of Snow and Ashes (Outlander, #6)',
'cover': 'http://books.google.com/books/content?id=N0Oh9YuuI9oC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Green Mile',
'cover': 'http://books.google.com/books/content?id=XCccAQAAIAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'The Two Towers (The Lord of the Rings, #2)',
'cover': 'http://books.google.com/books/content?id=12e8PJ2T7sQC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "The Doll's House (The Sandman, #2)",
'cover': 'http://books.google.com/books/content?id=lLk8xwEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'Bone: The Complete Edition',
'cover': 'http://books.google.com/books/content?id=-D9KDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "Band of Brothers: E Company, 506th Regiment, 101st Airborne from Normandy to Hitler's Eagle's Nest",
'cover': 'http://books.google.com/books/content?id=8Q41xjSUeZsC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Kissing Hand',
'cover': 'http://books.google.com/books/content?id=pWPjgOJKv3AC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Dead Beat (The Dresden Files, #7)',
'cover': 'http://books.google.com/books/content?id=kJJdRiEVHxYC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Death Note, Vol. 1: Boredom (Death Note, #1)',
'cover': 'http://books.google.com/books/content?id=pYLwAQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Complete Anne of Green Gables Boxed Set (Anne of Green Gables, #1-8)',
'cover': 'http://books.google.com/books/content?id=UmaTEAAAQBAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': "Fool's Fate (Tawny Man, #3)",
'cover': 'http://books.google.com/books/content?id=3cKuxI_bc9gC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Gates of Fire',
'cover': 'http://books.google.com/books/content?id=vcxlHkUGf_wC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Proven Guilty (The Dresden Files, #8)',
'cover': 'http://books.google.com/books/content?id=33cODAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'A Clash of Kings (A Song of Ice and Fire, #2)',
'cover': 'http://books.google.com/books/content?id=v7eWDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'White Night (The Dresden Files, #9)',
'cover': 'http://books.google.com/books/content?id=ibyMDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "Ina May's Guide to Childbirth",
'cover': 'http://books.google.com/books/content?id=q1GNRjS8bdkC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Going Postal (Discworld, #33; Moist von Lipwig, #1)',
'cover': 'http://books.google.com/books/content?id=ImTXB14VxdsC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Voyager (Outlander, #3)',
'cover': 'http://books.google.com/books/content?id=10Fsbx4Nah0C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Dance with the Devil (Dark-Hunter #3)',
'cover': 'http://books.google.com/books/content?id=am3a2gZgAjkC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Winds of War (The Henry Family, #1)',
'cover': 'http://books.google.com/books/content?id=BnGNB0EtwZEC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Brothers K',
'cover': 'http://books.google.com/books/content?id=rFg_h5iuOXkC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'And the Band Played On: Politics, People, and the AIDS Epidemic',
'cover': 'http://books.google.com/books/content?id=v3kgvUsV9tcC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "The Ultimate Hitchhiker's Guide to the Galaxy (Hitchhiker's Guide to the Galaxy, #1-5)",
'cover': 'http://books.google.com/books/content?id=mO-62VxpLe0C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Physician (Cole Family Trilogy, #1)',
'cover': 'http://books.google.com/books/content?id=lQvGCKC2_vIC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "The King of Attolia (The Queen's Thief, #3)",
'cover': 'http://books.google.com/books/content?id=uxfXzgEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'The Well of Ascension (Mistborn, #2)',
'cover': 'http://books.google.com/books/content?id=Y-41Q9zk32kC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Miraculous Journey of Edward Tulane',
'cover': 'http://books.google.com/books/content?id=oWh-tgUgAxcC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Batman: The Killing Joke',
'cover': 'http://books.google.com/books/content?id=s3yPEAAAQBAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'The Book Thief',
'cover': 'http://books.google.com/books/content?id=rk2MDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "Cursor's Fury (Codex Alera, #3)",
'cover': 'http://books.google.com/books/content?id=8cOLDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "Man's Search for Meaning",
'cover': 'http://books.google.com/books/content?id=Tx92CgAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Night Play (Dark-Hunter #5, Were-Hunter #1)',
'cover': 'http://books.google.com/books/content?id=9uHX1JMPw50C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Godfather',
'cover': 'http://books.google.com/books/content?id=acy0U6WyM7MC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Jayber Crow',
'cover': 'http://books.google.com/books/content?id=6NkREAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Fellowship of the Ring (The Lord of the Rings, #1)',
'cover': 'http://books.google.com/books/content?id=aWZzLPhY4o0C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'A Fine Balance',
'cover': 'http://books.google.com/books/content?id=2kuoQJmZ_jkC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "Boy's Life",
'cover': 'http://books.google.com/books/content?id=zl-Hbye_gL8C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Battle Cry of Freedom',
'cover': 'http://books.google.com/books/content?id=GXfGuNAvm7AC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Power of One (The Power of One, #1)',
'cover': 'http://books.google.com/books/content?id=khEua4UXieMC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Nonviolent Communication: A Language of Life',
'cover': 'http://books.google.com/books/content?id=A3qACgAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Winnie-the-Pooh (Winnie-the-Pooh, #1)',
'cover': 'http://books.google.com/books/content?id=AGdblU8iT0kC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Lover Eternal (Black Dagger Brotherhood, #2)',
'cover': 'http://books.google.com/books/content?id=EbCJDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "Maus I: A Survivor's Tale: My Father Bleeds History (Maus, #1)",
'cover': 'http://books.google.com/books/content?id=6fx6tKzPyLkC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'First They Killed My Father: A Daughter of Cambodia Remembers',
'cover': 'http://books.google.com/books/content?id=_1CFzo8E2XIC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Lorax',
'cover': 'http://books.google.com/books/content?id=-6_xAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Walking Dead, Book One (The Walking Dead #1-12)',
'cover': 'http://books.google.com/books/content?id=2MdNtQAACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'Drums of Autumn (Outlander, #4)',
'cover': 'http://books.google.com/books/content?id=b0Hvl7Q_BuIC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'A Light in the Attic',
'cover': 'http://books.google.com/books/content?id=5w-qDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Exodus',
'cover': 'http://books.google.com/books/content?id=8H9E00e5PSwC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Peace Is Every Step: The Path of Mindfulness in Everyday Life',
'cover': 'http://books.google.com/books/content?id=J7m8p1ngZKwC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Son of the Shadows (Sevenwaters, #2)',
'cover': 'http://books.google.com/books/content?id=Df6XdMOAekgC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Night (The Night Trilogy #1)',
'cover': 'http://books.google.com/books/content?id=VUjdAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'For a Few Demons More (The Hollows, #5)',
'cover': 'http://books.google.com/books/content?id=ya3Nq-_dqG8C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Blood Rites (The Dresden Files, #6)',
'cover': 'http://books.google.com/books/content?id=mMw5BhdgLFwC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Copper Sun',
'cover': 'http://books.google.com/books/content?id=ps_yWzuxz_gC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Letters to a Young Poet',
'cover': 'http://books.google.com/books/content?id=_wofmBiXXv0C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Matilda',
'cover': 'http://books.google.com/books/content?id=ggbLDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Dragonfly in Amber (Outlander, #2)',
'cover': 'http://books.google.com/books/content?id=BYAFHeaLWpsC&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'Thud! (Discworld, #34; City Watch #7)',
'cover': 'http://books.google.com/books/content?id=3uSp4UkrnasC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'When Nietzsche Wept', 'cover': None},
{'title': 'Autobiography of Red',
'cover': 'http://books.google.com/books/content?id=w-3Ru_r1PpEC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Half of a Yellow Sun',
'cover': 'http://books.google.com/books/content?id=eQh3sfhTVNsC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Wild Magic (Immortals, #1)',
'cover': 'http://books.google.com/books/content?id=xTGYCgAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Term Limits',
'cover': 'http://books.google.com/books/content?id=o62c1e0rYpMC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Crush',
'cover': 'http://books.google.com/books/content?id=zobVDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Death Masks (The Dresden Files, #5)',
'cover': 'http://books.google.com/books/content?id=oF6LDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Adventures of Sherlock Holmes',
'cover': 'http://books.google.com/books/content?id=t5ZXBAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Pillars of the Earth (Kingsbridge, #1)',
'cover': 'http://books.google.com/books/content?id=QYYQDAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Paradise (Second Opportunities, #1)',
'cover': 'http://books.google.com/books/content?id=Ag7GwAEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': "Ender's Shadow (The Shadow Series, #1)",
'cover': 'http://books.google.com/books/content?id=PpEz47zsLEwC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Lover Revealed (Black Dagger Brotherhood, #4)',
'cover': 'http://books.google.com/books/content?id=iDSMDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Walking Dead, Vol. 3: Safety Behind Bars',
'cover': 'http://books.google.com/books/content?id=_Z1svgEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'The Pale Horseman (The Saxon Stories, #2)',
'cover': 'http://books.google.com/books/content?id=2S4NkAEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api'},
{'title': 'The Lords of Discipline',
'cover': 'http://books.google.com/books/content?id=uTiquE4a8_cC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Gone with the Wind',
'cover': 'http://books.google.com/books/content?id=4I5fEAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'Small Gods (Discworld, #13)', 'cover': None},
{'title': 'Kane and Abel (Kane and Abel, #1)',
'cover': 'http://books.google.com/books/content?id=QJm0nuU6hqwC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'A Hat Full of Sky (Discworld, #32; Tiffany Aching, #2)',
'cover': 'http://books.google.com/books/content?id=sZ8x3wSOQ2YC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': "The Complete Grimm's Fairy Tales",
'cover': 'http://books.google.com/books/content?id=k31NFutTNRQC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'No Rest for the Wicked (Immortals After Dark, #2)',
'cover': 'http://books.google.com/books/content?id=8zSYCgAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Source',
'cover': 'http://books.google.com/books/content?id=t7UNykqMKrMC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'},
{'title': 'The Great Divorce',
'cover': 'http://books.google.com/books/content?id=2EDARL4gw20C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api'}]
In [157]:
len(cover_urls)
Out[157]:
100
In [172]:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import PIL
import urllib
!pip install pillow
Requirement already satisfied: pillow in /home/jchen/miniconda3/lib/python3.11/site-packages (10.1.0)
In [179]:
for book in cover_urls:
try:
cov = np.array(PIL.Image.open(urllib.request.urlopen(book['cover'])))
#img = mpimg.imread(cov)
plt.imshow(cov)
plt.title(book['title'])
plt.axis('off')
except Exception as e:
print(f"Error displaying cover for '{book['title']}': {e}")
Error displaying cover for 'Season of Mists (The Sandman, #4)': 'NoneType' object has no attribute 'timeout'
Error displaying cover for 'When Nietzsche Wept': 'NoneType' object has no attribute 'timeout'
Error displaying cover for 'Small Gods (Discworld, #13)': 'NoneType' object has no attribute 'timeout'
Trying to display in a grid
In [180]:
from mpl_toolkits.axes_grid1 import ImageGrid
In [181]:
fig = plt.figure(figsize=(4., 4.))
<Figure size 400x400 with 0 Axes>
In [182]:
grid = ImageGrid(fig, 111,
nrows_ncols=(10, 10), # creates 2x2 grid of axes
axes_pad=0.1, # pad between axes in inch.
)
In [209]:
#put image array data into a list
book_covers = []
for book in cover_urls:
try:
book_covers.append(np.array(PIL.Image.open(urllib.request.urlopen(book['cover']))))
except Exception as e:
print(f"Error displaying cover for '{book['title']}': {e}")
Error displaying cover for 'Season of Mists (The Sandman, #4)': 'NoneType' object has no attribute 'timeout' Error displaying cover for 'When Nietzsche Wept': 'NoneType' object has no attribute 'timeout' Error displaying cover for 'Small Gods (Discworld, #13)': 'NoneType' object has no attribute 'timeout'
In [205]:
#for ax, img in zip(grid, book_covers):
# Iterating over the grid returns the Axes.
# try:
#img = mpimg.imread(cov)
# ax.imshow(cov)
# except Exception as e:
# print(f"Error displaying cover for '{book['title']}': {e}")
len(book_covers)
Out[205]:
97
In [216]:
fig = plt.figure(figsize = (40., 40.))
fig.tight_layout(pad = 20.0)
for i in range(97):
plt.subplot(10,10,i+1) #i+1 ensures the one ur on is that position in the grid?
plt.xticks([])
plt.yticks([])
plt.imshow(book_covers[i])
# plt.xlabel(cover_urls[i]['title']) titles don't match anymore since some books don't have covers
plt.show()