ぐるなびAPIとホットペッパーAPIで個室のある飲み屋さんをPythonで一覧表示

## はじめに
### 自己紹介
Qiitaへ2回目の投稿です。プログラミング未経験でUdacityを学び、昨年の10月にData Scientist Nanodegreeを修了しました。まだまだひよっこです。コードが汚いかもしれませんが温かい目で見守ってください。

### モチベーション
1. TwitterAPIしか使ったことがなかったので、他のAPIも使ってみたかった。
2. 実生活で役に立ちそうなコードを書いてみたかった。

会社で飲み会の幹司をしていると、、、
・ 個室付きのお店を探すのが大変
・ 直近で使用したお店を選択すると、「ここ前にもきたな〜」と呟く人がいる
<span>　</span> (悪気はないと思うのですが、幹司をしていると少し気になってしまう)
・ しかし、田舎だと行ける飲み屋さんが限られてくる
・ 行ったことのないお店をチョイスすると、駅から遠かったりする
・ 長い時間サーチしていると、どこのお店を見たのかわからなくなってしまう
<span>　</span>  (能力が低いだけですが...)
というような面倒が多いので、APIを使うことで便利にできないかな〜と思いました。

### ざっくりとした要件定義
というわけで、
Input ... [駅名、県名]
Output ... [お店の名前、住所、url、予算]を一覧表で取得
Condition ... [駅から500m以内、個室あり]
というようなコードを書いてみます。

**コードをコピペしただけでは動きません。**
**ぐるなび・ホットペッパーのサイトからAPIキーを入手してコードに代入してください。**

## コード
### コード全体
```python:koshitsu.ipynb
# libraryをimport
import json
import requests
import urllib.parse
import pandas as pd

# 駅名・県名をinput
station ='志木'
pref='埼玉県'

# Rail APIを使って駅名・県名から駅の緯度・経度を取得
def RailAPI(station, pref):
    station_url =urllib.parse.quote(station)
    pref_url =urllib.parse.quote(pref)
    api='http://express.heartrails.com/api/json?method=getStations&name={station_name}&prefecture={pref_name}'
    url=api.format(station_name=station_url, pref_name=pref_url)
    response=requests.get(url)
    result_list = json.loads(response.text)['response']['station']
    lng=result_list[0]['x']
    lat=result_list[0]['y']
    return lat, lng

lat_st, lng_st =RailAPI(station, pref)

# HotpepperAPIを使って駅の緯度・経度から飲み屋の情報を取得
def HotpepperAPI(lat, lng):
    api_key=""　#自身で取得したAPI keyを入力
    api = "http://webservice.recruit.co.jp/hotpepper/gourmet/v1/?" \
            "key={key}&lat={lat}&lng={lng}&free_drink=1&private_room=1&course=1range=2&count=100&order=1&format=json"
    url=api.format(key=api_key,lat=lat_st, lng=lng_st)
    response = requests.get(url)
    result_list = json.loads(response.text)['results']['shop']
    shop_datas=[]
    for shop_data in result_list:
        shop_datas.append([shop_data["name"],shop_data["address"],shop_data["urls"]['pc'], shop_data["budget"]['average'], 'Hotpepper'])
    return shop_datas

columns = ['name','address', 'url', 'budget', 'source']
HP_data =pd.DataFrame(HotpepperAPI(lat_st, lng_st), columns=columns)

# ぐるなびAPIを使って駅の緯度・経度から飲み屋の情報を取得
def GurunaviAPI(lat, lng):
    api_key=""　#自身で取得したAPI keyを入力
    api = "https://api.gnavi.co.jp/RestSearchAPI/v3/?" \
            "keyid={key}&latitude={lat}&longitude={lng}&range=2&private_room=1&bottomless_cup=1&hit_per_page=100"
    url=api.format(key=api_key,lat=lat_st, lng=lng_st)
    response = requests.get(url)
    result_list = json.loads(response.text)['rest']
    shop_datas=[]
    for shop_data in result_list:
        shop_datas.append([shop_data["name"],shop_data["address"],shop_data["url"], shop_data["budget"], "ぐるなび"])
    return shop_datas

columns = ['name', 'address', 'url', 'budget', 'source']
G_data =pd.DataFrame(GurunaviAPI(lat_st, lng_st), columns=columns)

# HotpepperAPIとぐるなびAPIのデータを統合
total_data=pd.concat([G_data, HP_data])
```
### 駅名・県名から、駅の緯度・経度を取得
ぐるなびとHotpepperの最寄駅検索を使用すると、駅から遠い飲食店も表示されてしまします。
そこで、[RailAPI](http://express.heartrails.com/api.html#station)を使用して駅名の緯度・経度を取得することにしました。

また、他県に同一名称の駅名が存在した場合のために、県名も変数として入力します。
(県内に同一名称の駅名が存在した場合は誤った結果が出力される可能性があります。)

```python:koshitsu.ipynb
# Rail APIを使って駅名・県名から駅の緯度・経度を取得
def RailAPI(station, pref):
    station_url =urllib.parse.quote(station)
    pref_url =urllib.parse.quote(pref)
    api='http://express.heartrails.com/api/json?method=getStations&name={station_name}&prefecture={pref_name}'
    url=api.format(station_name=station_url, pref_name=pref_url)
    response=requests.get(url)
    result_list = json.loads(response.text)['response']['station']
    lng=result_list[0]['x']
    lat=result_list[0]['y']
    return lat, lng
lat_st, lng_st =RailAPI(station, pref)
```

### ホットペッパーAPIから飲み屋を抽出
[ホットペッパーAPI](https://webservice.recruit.co.jp/hotpepper/reference.html)を使用して飲み屋さんの情報を取得します。設定したパラメーターは以下の通り。

- lat={lat} ... RailAPIで入手した緯度
- lng={lng} ... RailAPIで入手した経度
- free_drink=1 ... 飲み放題あり
- private_room=1 ... 個室あり
- course=1 ... コース料理あり
- range=2 ... 指定した緯度・経度から半径500m以内
- count=100 ... 100件を抽出<br>
<span>　</span> (大都会でなければ100件以内でおさまります。)

参考文献 ... [Hotpepper API を使って指定した地点の近くの飲食店を検索する](https://coffee-nominagara.com/hotpepper-api)

```python:koshitsu.ipynb
# HotpepperAPIを使って駅の緯度・経度から飲み屋の情報を取得
def HotpepperAPI(lat, lng):
    api_key=""　#自身で取得したAPI keyを入力
    api = "http://webservice.recruit.co.jp/hotpepper/gourmet/v1/?" \
            "key={key}&lat={lat}&lng={lng}&free_drink=1&private_room=1&course=1&range=2&count=100&order=1&format=json"
    url=api.format(key=api_key,lat=lat_st, lng=lng_st)
    response = requests.get(url)
    result_list = json.loads(response.text)['results']['shop']
    shop_datas=[]
    for shop_data in result_list:
        shop_datas.append([shop_data["name"],shop_data["address"],shop_data["urls"]['pc'], shop_data["budget"]['average'], 'Hotpepper'])
    return shop_datas
```

### 抽出したホットペッパーの飲み屋をDataFrameに変換
pandasを用いてリストを[DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)に変換。

```python:koshitsu.ipynb
columns = ['name','address', 'url', 'budget', 'source']
HP_data =pd.DataFrame(HotpepperAPI(lat_st, lng_st), columns=columns)
```

### ぐるなびAPIから飲み屋を抽出
[ぐるなびAPI](https://api.gnavi.co.jp/api/manual/)を使用。パラメーターは以下。

:::note warn
警告
2021年6月31日をもって、ぐるなびの無料APIのサービスは終了しています。
:::

- latitude={lat} ... RailAPIで入手した緯度
- longitude={lng} ... RailAPIで入手した経度
- range=2 ... 指定した緯度・経度から半径500m以内
- private_room=1 ... 個室あり
- bottomless_cup=1 ... 飲み放題あり
- hit_per_page=100 ... 100件を抽出

```python:koshitsu.ipynb
# ぐるなびAPIを使って駅の緯度・経度から飲み屋の情報を取得
def GurunaviAPI(lat, lng):
    api_key=""　#自身で取得したAPI keyを入力
    api = "https://api.gnavi.co.jp/RestSearchAPI/v3/?" \
            "keyid={key}&latitude={lat}&longitude={lng}&range=2&private_room=1&bottomless_cup=1&hit_per_page=100"
    url=api.format(key=api_key,lat=lat_st, lng=lng_st)
    response = requests.get(url)
    result_list = json.loads(response.text)['rest']
    shop_datas=[]
    for shop_data in result_list:
        shop_datas.append([shop_data["name"],shop_data["address"],shop_data["url"], shop_data["budget"], "ぐるなび"])
    return shop_datas
```

### 抽出したぐるなびの飲み屋をDataFrameに変換
```python:koshitsu.ipynb
columns = ['name', 'address', 'url', 'budget', 'source']
G_data =pd.DataFrame(GurunaviAPI(lat_st, lng_st), columns=columns)
```

### 一つの表にまとめる
pandasの[concat](http://sinhrks.hatenablog.com/entry/2015/01/28/073327)を用いて表を結合。

```python:koshitsu.ipynb
# HotpepperAPIとぐるなびAPIのデータを統合
total_data=pd.concat([G_data, HP_data])
```
ほんとは重複したデータを一つにまとめたかったのですが、、、
・ 電話番号...HotpepperAPIで取得できず
・ 住所・店名... ぐるなびとホットペッパーで微妙に表記が異なっている
・ 店名のID... ぐるなびとホットペッパーで異なっている
・ 緯度・経度... ぐるなびとホットペッパーで異なっている
ということで断念しました。

## 具体例
### Input
```python:koshitsu.ipynb
station ='志木'
pref='埼玉県'
```
### Output
![Screen Shot 2020-02-10 at 19.20.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522259/c9e17b48-18f5-380d-6b6c-02c87bc11e3e.png)

## 感想
全ての飲食店に一意の番号が割り振られてると、Outputデータをきれいにできるんだけどな〜。国策で実施されないかな～。現実的じゃないのかな〜。