import pandas as pd
import urllib3
import json
import requests
from PIL import Image
from io import BytesIO
import matplotlib. pyplot as plt
from datetime import date
[docs]def search_artwork_by_culture(apikey,culture,page):
"""
Search Artwork by culture from the The Harvard Museum API based on query parameters.
Parameters
----------
apikey : String
your API key for The Harvard Museum API
culture : String
The culture you want to look up.ex."Chinese"
page : String
This API could only return 100 records per request ar maxium. One request is counted as 1 page.
if you want to see more records. Enter the number of Page. ex. "2" or "3"
Note: only integer in string format.Please enter "1" at the first time.
Returns
-------
pandas.core.frame.DataFrame
A dataframe that contains the 'id',"title",'objectnumber','century','worktypes','culture','technique','medium','description',
'classificationid','colorcount' based on thee query_parameter you entered.
Examples
--------
>>>import pandas as pd
>>>import json
>>>import urllib3
>>>search_artwork_by_culture(apikey="your api key",culture="Chinese",page="1")
>>> A dataframe
"""
try:
try:
# request data
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.harvardartmuseums.org/object',
fields = {
'apikey':apikey ,
"size":"100",
"culture":culture,
"page":page
})
except HTTPError as error:
print(f'HTTP error occurred: {error}')
except Exception as other_error:
print(f'Other error occurred: {other_error}')
else:
print('The request successes!')
record = json.loads(r.data)
#generate dataframe
df = pd.DataFrame(record["records"])
final_df=df[['id',"title",'objectnumber','century','worktypes','culture','technique','medium','description','classificationid','colorcount']]
return final_df
except:
print("Sorry! No result! Please enter strings for all parameters. Or Enter another culture.")
[docs]def function_search_for_artworks(title,vague_search,apikey):
"""
Search Artwork by title from the The Harvard Museum API based on query parameters.
Parameters
----------
apikey : String
your API key for The Harvard Museum API
title : String
The title of the artwork you want to look up.ex."Pouring Vessel"
vague_search : Boolean
True: return all the artwork contains the title
False:return one artwork has that exactly title
Note: When you enter False, and your title is not exactly the same as the havard museum provide.
You will receive nothing.
Returns
-------
pandas.core.frame.DataFrame
A dataframe that contains some information about the artwork based on the title you entered.
Examples
--------
>>>import pandas as pd
>>>import json
>>>import urllib3
>>>function_search_for_artworks(title="Pouring Vessel", vague_search=True,apikey="your api key")
>>> A dataframe contains many records
>>>function_search_for_artworks(title="Pouring Vessel", vague_search=False,apikey="your api key")
>>> A dataframe contains one record
"""
try:
final_result=[]
all_df=[]
# I can only get 100 records per requests at maxium, a request is counted as a page.
#Thus, the first request serves to check how many requests I need to get full records.
try:
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.harvardartmuseums.org/object',
fields = {
'apikey':apikey,
"title":title,
"size":"100",
})
except HTTPError as error:
print(f'HTTP error occurred: {error}')
except Exception as other_error:
print(f'Other error occurred: {other_error}')
else:
print('The request successes!')
object = json.loads(r.data)
info = pd.DataFrame(object["info"],index=[0])
# pages indicates the number of requests I need to get full record. Thus, I need to get total pages first.
total_pages=int(info['pages'])
#Use for loop to get all records
for i in range(1,total_pages+1):
r2 = http.request('GET', 'https://api.harvardartmuseums.org/object',
fields = {
'apikey':apikey,
"size":"100",
"page":str(i),
"title":title,
})
print(str(i),end='')
record = json.loads(r2.data)
final_result.append(record)
df = pd.DataFrame(final_result)
#extract the actual content of full records
for p in range(0,total_pages):
df_1=pd.DataFrame(df["records"].iloc[p])
# Choose the columns I needed
all_df.append(df_1[['id',"title",'objectnumber','century','worktypes','culture','technique','medium','description','classificationid','colorcount']])
# Combine all the dfs I get
finalqueryresult = pd.concat(all_df, ignore_index=True)
if vague_search==True:
all_items=finalqueryresult[finalqueryresult.apply(lambda row: row.astype(str).str.contains(title).any(), axis=1)]
return all_items
if vague_search==False:
exact_searching_result=finalqueryresult[finalqueryresult['title']==title]
exact_searching_result_df=exact_searching_result.drop_duplicates(subset=['id', 'title'], keep=False)
return exact_searching_result_df
except:
print("Please enter strings for all parameters! Or try another title. :D")
[docs]def search_for_images_by_width(width,apikey, page):
"""
Search images by width from the The Harvard Museum API based on query parameters.
Parameters
----------
apikey : String
your API key for The Harvard Museum API
width : String
The width of the image. ex.">1000"
page : String
This funtion could only return 10 records per request. One request is counted as 1 page.
if you want to see more records. Enter the number of Page. ex. "2" or "3"
Note: only integer in string format.Please enter "1" at the first time.
Returns
-------
matplotlib.image.AxesImage
10 images
Examples
--------
>>>import pandas as pd
>>>import json
>>>import urllib3
>>>import requests
>>>from PIL import Image
>>>from io import BytesIO
>>>import matplotlib. pyplot as plt
>>>search_for_images_by_size(width=">1000",apikey="your api key")
>>> An matplotlib.image.AxesImage
"""
try:
try:
# request images by width
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.harvardartmuseums.org/image',
fields = {
'apikey':apikey ,
"size":"10",
"width":width,
"page":page
})
except HTTPError as error:
print(f'HTTP error occurred: {error}')
except Exception as other_error:
print(f'Other error occurred: {other_error}')
else:
print('The request successes!')
data = json.loads(r.data)
pd.set_option('display.max_colwidth', None)
df = pd.DataFrame(data["records"])
urls=df['baseimageurl']
all=[]
#collect all images' urls from the response
for u in urls:
#read the images' urls into real image
response = requests.get(str(u))
img=Image.open(BytesIO(response.content))
all.append(img)
plt.figure(figsize=(20,10))
columns = 5
for i, image in enumerate(all):
try:
plt.subplot(len(all) / columns + 1, columns, i + 1)
plt.imshow(image)
except:
continue
except:
print("No result. Please enter string for all parameters. Or try other size. :D")
[docs]def search_for_images_by_height(height,apikey, page):
"""
Search images by size from the The Harvard Museum API based on query parameters.
Parameters
----------
apikey : String
your API key for The Harvard Museum API
height : String
The height of the image. ex. ">400"
page : String
This funtion could only return 10 records per request. One request is counted as 1 page.
if you want to see more records. Enter the number of Page. ex. "2" or "3"
Note: only integer in string format.Please enter "1" at the first time.
Returns
-------
matplotlib.image.AxesImage
10 images
Examples
--------
>>>import pandas as pd
>>>import json
>>>import urllib3
>>>import requests
>>>from PIL import Image
>>>from io import BytesIO
>>>import matplotlib. pyplot as plt
>>>search_for_images_by_size(height=">400",apikey="your api key")
>>> An matplotlib.image.AxesImage
"""
try:
try:
# request images by width and height
http = urllib3.PoolManager()
r = http.request('GET', 'https://api.harvardartmuseums.org/image',
fields = {
'apikey':apikey ,
"size":"10",
"Height":height,
"page":page
})
except HTTPError as error:
print(f'HTTP error occurred: {error}')
except Exception as other_error:
print(f'Other error occurred: {other_error}')
else:
print('The request successes!')
data = json.loads(r.data)
pd.set_option('display.max_colwidth', None)
df = pd.DataFrame(data["records"])
urls=df['baseimageurl']
all=[]
#collect all images' urls from the response
for u in urls:
#read the images' urls into real image
response = requests.get(str(u))
img=Image.open(BytesIO(response.content))
all.append(img)
plt.figure(figsize=(20,10))
columns = 5
for i, image in enumerate(all):
try:
plt.subplot(len(all) / columns + 1, columns, i + 1)
plt.imshow(image)
except:
continue
except:
print("No result. Please enter string for all parameters. Or try other size. :D")
[docs]def exhibition_explorer(apikey,exhibition):
"""
Get the information of artwork for a particualr exhibition in the Harvard Museum from the The Harvard Museum API based on query parameters.
Parameters
----------
apikey : String
your API key for The Harvard Museum API
exhibition : String
The exact name of exhibition that showed in the Harvard Museum website.
Returns
-------
pandas.core.frame.DataFrame
A dataframe that contains the information about artworks appearing in that exhibition.
Examples
--------
>>>import pandas as pd
>>>import json
>>>import urllib3
>>>exhibition_explorer(apikey="your api key",exhibition="Botticelli's Witness: Changing Style in a Changing Florence")
>>> A dataframe
"""
# Send the first request to get the exhibition id for the exhibitions
http = urllib3.PoolManager()
try:
try:
r = http.request('GET', 'https://api.harvardartmuseums.org/exhibition',
fields = {
'apikey': apikey,
'exact_title':exhibition
})
except HTTPError as error:
print(f'HTTP error occurred: {error}')
except Exception as other_error:
print(f'Other error occurred: {other_error}')
else:
print('The request successes!')
data = json.loads(r.data)
pd.set_option('display.max_colwidth', None)
df = pd.DataFrame(data["records"])
exhibitionid=int(df['exhibitionid'])
#Use the exhibition id to send the second request to get all the artwork in that exhibition.
r1 = http.request('GET', 'https://api.harvardartmuseums.org/object',
fields = {
'apikey': '544ea1bf-7cd9-4c94-96a7-9a4d4057c91a',
"size":"10",
"exhibition":str(exhibitionid)
})
data1 = json.loads(r1.data)
df_for_pieces = pd.DataFrame(data1["records"])
final_df=df_for_pieces[['id',"title",'objectnumber','century','worktypes','culture','technique','medium','description','classificationid','colorcount','colors','primaryimageurl']]
return final_df
except:
print("Please check your input, they have to be strings, and exhibition has to be exactly the same with the Harvard Museum Website.")
[docs]def artwork_for_today(apikey):
"""
Request an image of artwork that enter the Harvard Museum at today in history.
Parameters
----------
apikey : String
your API key for The Harvard Museum API
Returns
-------
PIL.JpegImagePlugin.JpegImageFile
an image
Examples
--------
>>>from io import BytesIO
>>>from datetime import date
>>>import urllib3
>>>import json
>>>import pandas as pd
>>>import matplotlib. pyplot as plt
>>>artwork_for_today(apikey="your api key")
>>> An Image
"""
#Read today's time
today = date.today()
print(f'Hi~ Today is {today}')
print("Start to prepare artwork for you! Good Luck")
today_month_day=str(today)[5:]
final_result=[]
all_df=[]
try:
http = urllib3.PoolManager()
for i in range(1,30):
#Get 3000 images for further selection
r1 = http.request('GET', 'https://api.harvardartmuseums.org/image',
fields = {
'apikey': apikey,
"size":"100",
"page":str(i)
})
print(str(i),end='')
data1 = json.loads(r1.data)
final_result.append(data1)
df1 = pd.DataFrame(final_result)
for p in range(0,29):
df_1=pd.DataFrame(df1["records"][p])
#Selection information on imageurl and dates
all_df.append(df_1[['id',"date","baseimageurl","description"]])
finalqueryresult = pd.concat(all_df, ignore_index=True)
finalqueryresult['date'] = pd.to_datetime(finalqueryresult.date)
finalqueryresult['new_date'] = finalqueryresult['date'].dt.strftime('%m-%d')
#Match the computer's time and artwork's date
new_date=finalqueryresult[finalqueryresult['new_date']==today_month_day]
#I just need it to display one photo for a particular date
urls=new_date['baseimageurl'].iloc[0]
response = requests.get(urls)
img = Image.open(BytesIO(response.content))
return img
except:
print("Sorry! No artwork enter Harvard Museum at today in the history~ Try Tomrrow Please~ : D")
[docs]def trendplot_for_particular_artwork_type(artwork_type, apikey):
"""
Gnerate a trend plot for the number of certain artwoork type during 10th -20th century's .
Parameters
----------
apikey : String
your API key for The Harvard Museum API
artwork_type : String
The artwork type you want to generate trend plot. ex."sculpture"
Returns
-------
A bar plot
A trend plot for 10th -20th century.
Examples
--------
>>>import urllib3
>>>import json
>>>import pandas as pd
>>>import matplotlib. pyplot as plt
>>>trendplot_for_particular_artwork_type(artwork_type="sculpture", apikey="your api key")
>>> An trend plot
"""
#Send the first request to check how many pages I need to get all results
try:
http = urllib3.PoolManager()
final_result=[]
all_df=[]
try:
r = http.request('GET', 'https://api.harvardartmuseums.org/object',
fields = {
'apikey': apikey,
"size":"100",
"worktype":str(artwork_type)
})
except HTTPError as error:
print(f'HTTP error occurred: {error}')
except Exception as other_error:
print(f'Other error occurred: {other_error}')
else:
print('The request successes!')
data = json.loads(r.data)
info = pd.DataFrame(data["info"],index=[0])
total_pages=int(info['pages'])
# Use the number of total pages to get all the results
for i in range(1,total_pages+1):
r1 = http.request('GET', 'https://api.harvardartmuseums.org/object',
fields = {
'apikey': apikey,
"size":"100",
"worktype":str(artwork_type),
"page":str(i)
})
print(str(i),end='')
data1 = json.loads(r1.data)
final_result.append(data1)
df1 = pd.DataFrame(final_result)
for p in range(0,total_pages):
df_1=pd.DataFrame(df1["records"][p])
all_df.append(df_1[['id',"title",'objectnumber',"century"]])
finalqueryresult = pd.concat(all_df, ignore_index=True)
#Find all BCE first:Before the century, since there are confusing.
finalqueryresult['patterns'] = finalqueryresult['century'].str.findall(r'BCE')
finalqueryresult['patterns_string']=finalqueryresult['patterns'].astype(str)
#Create another dataframe exclude BCE
df_without_bce=finalqueryresult[finalqueryresult['patterns_string']!="['BCE']"]
#Count the number of artwork for each century
tenth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("10th").any(), axis=1)])
eleventh=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("11th").any(), axis=1)])
twelfth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("12th").any(), axis=1)])
thirteenth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("13th").any(), axis=1)])
fourteenth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("14th").any(), axis=1)])
fifteenth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("15th").any(), axis=1)])
sixteenth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("16th").any(), axis=1)])
seventeenth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("17th").any(), axis=1)])
eighteenth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("18th").any(), axis=1)])
nineteenth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("19th").any(), axis=1)])
twentieth=len(df_without_bce[df_without_bce.apply(lambda row: row.astype(str).str.contains("20th").any(), axis=1)])
#Generating trend plot
x=["10th","11th","12th","13th","14th","15th","16th","17th","18th","19th","20th"]
height = [tenth,eleventh,twelfth,thirteenth,fourteenth,fifteenth,sixteenth,seventeenth,eighteenth,nineteenth,twentieth]
plt.bar(x, height, color="orange", width=0.4)
plt.xlabel("Century")
plt.ylabel("Number of Artworks")
# add the number of cases on the top of each bars
x_position=[1,2,3,4,5,6,7,8,9,10,11]
for i in range(11):
plt.text(x = x_position[i]-1.2, y = height[i]+1, s = height[i])
plt.show()
except:
print("Sorry! No result! Please enter strings for all Parameters! Or please try another artwork type. :D")