Source code for final_project_shiyinglai.final_project_shiyinglai

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")