PUNK APIでクラフトビールの情報を取得しながらAPI利用を学ぶ🍻
Punk IPAというクラフトビールがありますよね。APIもある模様ですね!
注意ですが、 この記事を読むとビールのIPAとAPIがゲシュタルト崩壊していきます。
JavaScript初心者、APIやaxiosの利用が初めての人向け解説記事です。if文やfor文、配列やオブジェクトなどの基本構文についてはスキップして話をしています。こちらのaxiosサンプル集で見つけたAPIを使ってみました。
PUNK APIのページを見てみる
ブリュードッグのPunk IPAをもじってる感がすごいAPIですね。公式ではなく、サードパーティが作ってるジョークAPIだと思います。
説明文を見る限り、ブリュードッグのビール情報を取得するっぽいですね。
こちらがAPIのページらしいです。
Version 1 has now been shutdown. Upgrade to V2 it's easier & faster!
とのことなので、どうやら最近はv1を終えて、v2に移行していくみたいですね
まずはAPIを叩いてみる
https://api.punkapi.com/v2/beers
これがビール取得のAPIエンドポイント(URL)みたいですね
const axios = require('axios');
const main = async () => {
try {
const res = await axios.get('https://api.punkapi.com/v2/beers');
console.log(res.data);
} catch (error) {
console.error(error);
}
}
main();
実行してみると以下のような感じでクラフトビールの一覧と情報が取得できました。
省略・・・
{
id: 24,
name: 'The End Of History',
tagline: "The World's Strongest Beer.",
first_brewed: '06/2011',
description: 'The End of History: The name derives from the famous work of philosopher Francis Fukuyama, this is to beer what democracy is to history. Complexity defined. Floral, grapefruit, caramel and cloves are intensified by boozy heat.',
image_url: 'https://images.punkapi.com/v2/24.png',
abv: 55,
ibu: null,
target_fg: 1000,
target_og: 1112,
ebc: null,
srm: null,
ph: 4.4,
attenuation_level: 100,
volume: { value: 20, unit: 'litres' },
boil_volume: { value: 25, unit: 'litres' },
method: {
mash_temp: [Array],
fermentation: [Object],
twist: 'Nettles: 25g at end, Juniper: 25g at end'
},
ingredients: {
malt: [Array],
hops: [Array],
yeast: 'Wyeast 3522 - Belgian Ardennes™'
},
food_pairing: [
'Roasted wood pigeon with black pudding',
'Pan seared venison fillet with juniper sauce',
'Apricot coconut cake'
],
brewers_tips: "You'll have to get this one all the way down to -70°C. Taxidermy is not optional.",
contributed_by: 'Sam Mason <samjbmason>'
},
{
id: 25,
name: 'Bad Pixie',
tagline: 'Spiced Wheat Beer.',
first_brewed: '10/2008',
description: '2008 Prototype beer, a 4.7% wheat ale with crushed juniper berries and citrus peel.',
image_url: 'https://images.punkapi.com/v2/25.png',
abv: 4.7,
ibu: 45,
target_fg: 1010,
target_og: 1047,
ebc: 8,
srm: 4,
ph: 4.4,
attenuation_level: 79,
volume: { value: 20, unit: 'litres' },
boil_volume: { value: 25, unit: 'litres' },
method: {
mash_temp: [Array],
fermentation: [Object],
twist: 'Crushed juniper berries: 12.5g, Lemon peel: 18.8g'
},
ingredients: {
malt: [Array],
hops: [Array],
yeast: 'Wyeast 1056 - American Ale™'
},
food_pairing: [
'Poached sole fillet with capers',
'Summer fruit salad',
'Banana split'
],
brewers_tips: 'Make sure you have plenty of room in the fermenter. Beers containing wheat can often foam aggressively during fermentation.',
contributed_by: 'Sam Mason <samjbmason>'
}
Punk IPAをAPI経由で取得してみる
APIのリクエストパラメータにbeer_name
というKeyがあります。
しかも詳細の箇所をみると Punk
を指定するとPunk IPAの情報が取れるよみたいなことが書かれています。確信犯。
URLはこういう指定になります。
https://api.punkapi.com/v2/beers?beer_name=punk
JavaScriptからだとこんな書き方ですね。
const axios = require('axios');
const main = async () => {
try {
const res = await axios.get('https://api.punkapi.com/v2/beers?beer_name=punkipa');
console.log(res.data);
} catch (error) {
console.error(error);
}
}
main();
実行すると確かにPunk APIの情報一覧が取得できました。
・・・省略
{
id: 192,
name: 'Punk IPA 2007 - 2010',
tagline: 'Post Modern Classic. Spiky. Tropical. Hoppy.',
first_brewed: '04/2007',
description: "Our flagship beer that kick started the craft beer revolution. This is James and Martin's original take on an American IPA, subverted with punchy New Zealand hops. Layered with new world hops to create an all-out riot of grapefruit, pineapple and lychee before a spiky, mouth-puckering bitter finish.",
image_url: 'https://images.punkapi.com/v2/192.png',
abv: 6,
ibu: 60,
target_fg: 1010,
target_og: 1056,
ebc: 17,
srm: 8.5,
ph: 4.4,
attenuation_level: 82.14,
volume: { value: 20, unit: 'litres' },
boil_volume: { value: 25, unit: 'litres' },
method: { mash_temp: [Array], fermentation: [Object], twist: null },
ingredients: {
malt: [Array],
hops: [Array],
yeast: 'Wyeast 1056 - American Ale™'
},
food_pairing: [
'Spicy carne asada with a pico de gallo sauce',
'Shredded chicken tacos with a mango chilli lime salsa',
'Cheesecake with a passion fruit swirl sauce'
],
brewers_tips: "While it may surprise you, this version of Punk IPA isn't dry hopped but still packs a punch! To make the best of the aroma hops make sure they are fully submerged and add them just before knock out for an intense hop hit.",
contributed_by: 'Sam Mason <samjbmason>'
}
]
色々とPunk IPAの情報が出てきましたが、少し長いので最後のものだけ記事に表示させてます。このid:192
を次の手順で使ってみます。
Punk IPAの情報を1件だけ取得する
一覧の取得が出来ましたが、このAPIは1件だけ取得することも出来るみたいです。
ドキュメントページを読み進めるとSingle Beer
とRandom Beer
のAPIを発見できます。
どうやらビールの情報を一つ取得したり、ランダムでビール情報を取得したり出来る模様です。
1件だけ取得するSingle BeerはIDを指定して1件取得できるらしいです。
先程のPunk IPAのid: 192
の項目を指定してみます。
URLはhttps://api.punkapi.com/v2/beers/192
になりますね。
const axios = require('axios');
const main = async () => {
try {
const res = await axios.get('https://api.punkapi.com/v2/beers/192');
console.log(res.data);
} catch (error) {
console.error(error);
}
}
main();
$ node punkapi-test.js
[
{
id: 192,
name: 'Punk IPA 2007 - 2010',
tagline: 'Post Modern Classic. Spiky. Tropical. Hoppy.',
first_brewed: '04/2007',
description: "Our flagship beer that kick started the craft beer revolution. This is James and Martin's original take on an American IPA, subverted with punchy New Zealand hops. Layered with new world hops to create an all-out riot of grapefruit, pineapple and lychee before a spiky, mouth-puckering bitter finish.",
image_url: 'https://images.punkapi.com/v2/192.png',
abv: 6,
ibu: 60,
target_fg: 1010,
target_og: 1056,
ebc: 17,
srm: 8.5,
ph: 4.4,
attenuation_level: 82.14,
volume: { value: 20, unit: 'litres' },
boil_volume: { value: 25, unit: 'litres' },
method: { mash_temp: [Array], fermentation: [Object], twist: null },
ingredients: {
malt: [Array],
hops: [Array],
yeast: 'Wyeast 1056 - American Ale™'
},
food_pairing: [
'Spicy carne asada with a pico de gallo sauce',
'Shredded chicken tacos with a mango chilli lime salsa',
'Cheesecake with a passion fruit swirl sauce'
],
brewers_tips: "While it may surprise you, this version of Punk IPA isn't dry hopped but still packs a punch! To make the best of the aroma hops make sure they are fully submerged and add them just before knock out for an intense hop hit.",
contributed_by: 'Sam Mason <samjbmason>'
}
]
無事に1件だけ取得することが出来ました。
ビールの名前と画像だけ欲しい
データの加工タイムです。1件だけ取得できましたが、まだ情報量が多いですね。自分が利用したい、必要な情報だけ取得しましょう。
ビールの名前Punk IPA 2007-2010
と画像のhttps://images.punkapi.com/v2/192.png
を取得してみます。
基本的にはres.data
の後にKey名をドット(.)で繋げれば取得できます。
PUNK APIのこの場合、
- ビールの名前:
name
のKey - ビールの画像:
image_url
のKey
というKey名になっているので、以下のように書くことで名前と画像だけを抽出出来ます。
//省略
const res = await axios.get('https://api.punkapi.com/v2/beers/192');
console.log(res.data.name); //名前
console.log(res.data.image_url); //画像取得
//省略
実行してみるとどうでしょう。
$ node punkapi-test.js
undefined
undefined
...あれ。undefined
はデータが格納されてないということで、上手く取得できてないです。
ここはAPIあるあるです。res.data
に格納されるデータが配列形式になっている場合があります。その場合は[0]
などで配列の何番目を利用するかを指定する必要があります。
配列([]
)かオブジェクト({}
)かの見分け方はコンソールなどに表示された最初の記号が[
なのか{
なのかで見分けると良いと思います。
実はドキュメントページの例にも書いてありましたね。
1件だけ取得するSingle Beer
のAPIが配列(複数)で返ってくるのも仕様的にどうなんだろ?と思いつつ、仕方ないので書き換えてみます。
以下のように配列の0番目
を指定し、以降は.name
や.image_url
などドットとKey名で繋げていきます。
//省略
const res = await axios.get('https://api.punkapi.com/v2/beers/192');
console.log(res.data[0].name); //名前
console.log(res.data[0].image_url); //画像取得
//省略
これで名前と画像URLだけを取得できました。
$ node punkapi-test.js
Punk IPA 2007 - 2010
https://images.punkapi.com/v2/192.png
もっと深い階層のデータを取得してみる
yeastのkeyにある値を取得したい場合はどうすれば良いでしょうか。
yeast
は入れ子構造になっていて、ingredients
のKeyの子階層になっていることが分かります。ドットで接続していくことで子階層の深いデータにアクセスすることが出来ます。
//省略
const res = await axios.get('https://api.punkapi.com/v2/beers/192');
console.log(res.data[0].ingredients.yeast);
//省略
$ node punkapi-test.js
Wyeast 1056 - American Ale™
yeast
と同階層のmalt
やhops
にアクセスする場合は、[Array]
となっていて表示上省略されています。一度res.data[0].ingredients
をconsole.logで表示してみましょう。
//省略
console.log(res.data[0].ingredients);
//省略
$ node punkapi-test.js
{
malt: [ { name: 'Extra Pale', amount: [Object] } ],
hops: [
{
name: 'Ahtanum',
amount: [Object],
add: 'start',
attribute: 'bitter'
},
{
name: 'Chinook',
amount: [Object],
add: 'start',
attribute: 'bitter'
},
//省略
malt
もhops
も下の階層は配列になっていて、その中にオブジェクトが格納されていることが分かります。
hops
以下のChinook
の情報を取得してみます。Chinook
の箇所はhops以下の配列の2番目になります。配列の指定は0からスタートなので、2番目の配列は1を指定します。
//省略
console.log(res.data[0].ingredients.hops[1].name);
console.log(res.data[0].ingredients.hops[1].add);
console.log(res.data[0].ingredients.hops[1].amount);
console.log(res.data[0].ingredients.hops[1].attribute);
//省略
$ node punkapi-test.js
Chinook
start
{ value: 15, unit: 'grams' }
bitter
という感じで配列とオブジェクトの操作を行えました。
Punk IPAのビールの名前と画像だけの一覧が欲しい
1件だけ扱うではなく、一覧を作成してみましょう。ここでfor文を利用してデータを複数回処理します。
const axios = require('axios');
const main = async () => {
try {
const res = await axios.get('https://api.punkapi.com/v2/beers?beer_name=punkipa');
// console.log(res.data);
for (let i = 0, len = res.data.length; i < len; i++) {
console.log(res.data[i].name);
console.log(res.data[i].image_url);
}
} catch (error) {
console.error(error);
}
}
main();
$ node punkapi-test.js
Punk IPA 2010 - Current
https://images.punkapi.com/v2/106.png
Punk IPA 2007 - 2010
https://images.punkapi.com/v2/192.png
ちなみにPunkだけで調べるとPunk IPA以外のPunkと名のつくビールが表示されました。Punk IPA以外にも〇〇Punkみたいな名称、色々あるんですね。
まとめ
Punk APIはネーミング的にジョークAPIだと思ってましたが、APIの作りは比較的分かりやすく、扱いやすい印象でした。
途中でも書きましたが、Single Beerが配列で返ってくるのはどうなんでしょうね苦笑
皆さんもぜひPUNK APIを使って知らないクラフトビール(このAPIだとブリュードッグのものだけかもですが)と出会ってみて下さい。
そろそろ緊急事態宣言も空けてビール飲みに行けますかねぇ。
Discussion