Recently, I am studying Python again. So, as part of my study, I tried to create a class that would make the public API easier to use.
The code can be found here in the Repository (https://github.com/ironball1113/sakenowa_wrapper).
This is a project to publish the data collected from the app Sakeno, which has the concept of "recording the sake you drank and finding your favorite sake". In other words, it is data about sake. Details will be quoted from the public page. https://muro.sakenowa.com/sakenowa-data/
This is a project to publish data and popular brand information that quantifies the flavors of the sake app Sakenowa. Anyone can use it for free within the scope of the terms of use, and can display data on the EC site, create apps and services, and perform data analysis.
At Sakenowa, we analyze user's impression comments and quantify the flavor. In addition to this data, we will publish the following data including ranking information.
--The flavors of each brand are quantified from the six perspectives of gorgeous, mellow, profound, gentle, light, and dry. --Tags of flavor details for each brand (flavor tag) --Ranking of popular stocks in salmon --Other basic information of the brand
--Area list (GET / areas) --List of brands (GET / brands) --List of breweries (GET / breweries) --Ranking (GET / rankings) --Flavor chart (GET / flavor-charts) --Flavor tag list (GET / flavor-tags) --Flavor tags for each brand (GET / brand-flavor-tags)
sakenowa_wrapper I created a class because I thought it would be a little easier to call if I could use it in the pandas data frame format with just the endpoint information. It's easy to do, and the API response is finally returned to a dataframe.
sakenowa_wrapper.py
import ast
import urllib.request
import pandas as pd
from pandas.core.frame import DataFrame
class SakenowaAPI(object):
urls = {
"areas": "https://muro.sakenowa.com/sakenowa-data/api/areas",
"brands": "https://muro.sakenowa.com/sakenowa-data/api/brands",
"breweries": "https://muro.sakenowa.com/sakenowa-data/api/breweries",
"rankings": "https://muro.sakenowa.com/sakenowa-data/api/rankings",
"flavor-charts": "https://muro.sakenowa.com/sakenowa-data/api/flavor-charts",
"flavor-tags": "https://muro.sakenowa.com/sakenowa-data/api/flavor-tags",
"brand-flavor-tags": "https://muro.sakenowa.com/sakenowa-data/api/brand-flavor-tags",
}
def __init__(self, endpoint: str, ranking_type: str = None) -> None:
self.endpoint = endpoint
check_endpoint = self.endpoint in list(self.urls.keys())
if check_endpoint:
self.url = self.urls[self.endpoint]
self.ranking_type = ranking_type
print(f"\nThe current endpoint is {self.endpoint}")
if ranking_type is not None:
print(f"Rankings type is {ranking_type}")
print("=" * 30)
else:
raise ValueError("The argument is incorrect. Please specify again.")
def _get_body(self, url: str) -> str:
req = urllib.request.Request(url)
with urllib.request.urlopen(req) as res:
body = res.read()
return body.decode()
def _set_key(self) -> str:
if self.endpoint in ["areas", "brands", "breweries"]:
return self.endpoint
if self.endpoint == "flavor-charts":
return "flavorCharts"
if self.endpoint == "flavor-tags":
return "tags"
if self.endpoint == "brand-flavor-tags":
return "flavorTags"
if self.endpoint == "rankings" and self.ranking_type is not None:
return self.ranking_type
else:
return "Failure"
def set_df(self) -> DataFrame:
body = self._get_body(self.url)
dic = ast.literal_eval(body)
key = self._set_key()
return pd.DataFrame(dic[key])
Below is the trial code. Basically, only do the following:
The endpoints that can be specified with the Sakenowa API are as follows. Since rankings has a comprehensive ranking of popular brands and a regional ranking, an additional argument is required to specify which one to call. ex) SakenowaAPI("rankings", "overall") or SakenowaAPI("rankings", "areas")
test_sakenowa.py
from sakenowa_wrapper import SakenowaAPI
#When there is one argument such as areas
sakenowa_areas = SakenowaAPI("areas")
print(sakenowa_areas.set_df().head())
#rankings is for overall rankings
sakenowa_rank_overall = SakenowaAPI("rankings", "overall")
print(sakenowa_rank_overall.set_df().head())
#If the argument is incorrect
# sakenowa_failue = SakenowaAPI("failue")
# print(sakenowa_failue.set_df().head())
# --------------------Output result--------------------
# The current endpoint is areas
# ==============================
# id name
#0 1 Hokkaido
#1 2 Aomori Prefecture
#2 3 Iwate Prefecture
#3 4 Miyagi Prefecture
#4 5 Akita Prefecture
# The current endpoint is rankings
# Rankings type is overall
# ==============================
# rank score brandId
# 0 1 4.412219 109
# 1 2 4.100738 792
# 2 3 4.072851 660
# 3 4 4.072180 1033
# 4 5 4.065659 19
# ValueError:The argument is incorrect. Please specify again.
Also, the trial code for drawing flavor charts with matplotlib is below. For the radar chart creation part, I referred to this article. Draw a radar chart with Matplotlib (16 lines)
test_radar_chart.py
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sakenowa_wrapper import SakenowaAPI
sakenowa_flavor_charts = SakenowaAPI("flavor-charts")
dic = sakenowa_flavor_charts.make_dic()
df_copy = sakenowa_flavor_charts.set_df(dic).copy()
col_rename = {
"f1": "Fruity",
"f2": "Mellow",
"f3": "Heavy",
"f4": "Mild",
"f5": "Dry",
"f6": "Light",
}
brand_id = 2
renamed_cols = list(df_copy.rename(columns=col_rename).columns)[1:]
flavor_values = df_copy.query("brandId == @brand_id").values.tolist()[0][1:]
def plot_polar(labels, values, imgname):
angles = np.linspace(0, 2 * np.pi, len(labels) + 1, endpoint=True)
values = np.concatenate((values, [values[0]]))
fig = plt.figure()
ax = fig.add_subplot(111, polar=True)
ax.plot(angles, values, "o-")
ax.fill(angles, values, alpha=0.25)
ax.set_thetagrids(angles[:-1] * 180 / np.pi, labels)
fig.savefig(imgname)
plt.close(fig)
plot_polar(renamed_cols, flavor_values, "flavor.png ")
Sakenowa Data Project [Static type checking that starts loosely in Python](https://qiita.com/ocknamo/items/6341d0a7757c668782c8#%E3%81%8A%E3%81%BE%E3%81%91stub%E3%82%92% E8% 87% AA% E5% 8B% 95% E7% 94% 9F% E6% 88% 90% E3% 81% 99% E3% 82% 8B) Draw a radar chart with Matplotlib (16 lines)
Recommended Posts