🥟

「肉汁餃子のダンダダン」の店舗情報をWebスクレイピングして地図上に可視化してみる

2023/01/11に公開

概要

  • 最近ダンダダンていう居酒屋よく見るな〜」と思い、試しに地図上に可視化してみました。
  • 肉汁餃子のダンダダンは餃子が美味しい居酒屋です。
  • 餃子アイスも美味しいです。

https://www.dandadan.jp/

手順

1. ダンダダンのサイトから店舗情報をスクレイピング
2. 住所から緯度経度を取得(ジオコーディング)
3. kepler.glで可視化

1. ダンダダンのサイトから店舗情報をスクレイピング

まずはダンダダンのホームページの店舗情報から店舗名住所をスクレイピングしたいと思います。
GoogleCoraboratoryを用いてスクレイピングをします。
https://www.dandadan.jp/shop/

スクレイピングについては、はやたすさんの動画を参考にしました。

ライブラリのインポート

スクレイピングとデータ加工に必要なライブラリをインポートします。

# ライブラリのインポート
from bs4 import BeautifulSoup
import numpy as np
import pandas as pd
import requests

取得すべき情報を確認

ホームページのどこから情報を取得すればいいのかを確認します。
店舗情報のページを検証してみるとdivタグのshoplistのクラスの情報を取得すればいいということがわかりました。

スクレイピングの実行

それでは以下のような流れでcontentsという変数に取得した情報を格納します。

# ダンダダン店舗のURL
url = 'https://www.dandadan.jp/shop/'

# urlへのアクセス結果を、変数rに格納
r = requests.get(url)

# 取得結果を解析してsoupに格納
soup = BeautifulSoup(r.text)

# shopListクラスを持ったdivタグを全て取得して、変数contentsに格納
contents = soup.find_all('div', class_='shopList')

contentsの要素数を確認すると128個ありました。
すなわち128店舗の情報を取得できたということです。

1つ目の要素を確認してみましょう。

欲しいのは店舗名と住所なのですが余計な情報が色々含まれていますね。
divタグのshopNameというクラスから店舗名を、pタグのaddressというクラスから住所を取り出してみたいと思います。

# 店舗名の情報を変数shopnameに格納する
shopname = content.find('div', class_='shopName').text

# 住所の情報を変数addressに格納する
address = content.find('p', class_='address').text

確認してみます。
余計な文字列が含まれていますが、取りたい情報は取得できたのでよしとします。

取得した情報をデータフレーム化

それではfor文で128店舗分の店舗名と住所を取得し、データフレームにまとめたいと思います。

# 空のリストを作成
shopname_list = []
address_list = []

# forループ
for content in contents:
    # 店舗名の情報を変数shopnameに格納する
    shopname = content.find('div', class_='shopName').text
    # 住所の情報を変数addressに格納する
    address = content.find('p', class_='address').text

    # 空のリストに格納
    shopname_list.append(shopname)
    address_list.append(address)

# shopname_listとaddress_listをデータフレーム化
dnddn_df = pd.DataFrame(
    data={'shopname' : shopname_list,
          'address' : address_list}
          )

以下のようなデータフレームを作成することができました。

データの加工

余計な文字列が含まれているので削除したいと思います。
店舗名については「\t」以降を削除する処理を行います。
住所については「\n住所」、「\u3000」という文字列、「\r\n」以降の文字列が不要なのでそれらを削除する処理を行います。

# 店舗名の不要な部分を削除する関数
def shopname(name):
    s = name
    target = '\t\t\t'
    idx = s.find(target)
    return s[:idx]

# 住所の不要な部分を削除する関数
def Address(address):
    s = address[3:]
    target = '\xa0\n '
    idx = s.find(target)
    new_address = s[:idx]
    return new_address.replace('\u3000', '').replace('\r\n', '')

# shopnameの不要な部分を削除
dnddn_df['shopname'] = dnddn_df['shopname'].apply(lambda x: shopname(x))

# addressの不要な部分を削除
dnddn_df['address'] = dnddn_df['address'].apply(lambda x: Address(x))

綺麗なデータフレームにすることができました。

このデータフレームをcsvにして保存します。

2.住所から緯度経度を取得(ジオコーディング)

住所から緯度経度情報を取得する(いわゆるジオコーディング)には様々な方法がありますが、
今回は件数もそこまで多くないのでスプレッドシートカスタム関数を作成してジオコーディングを行いたいと思います。
詳しくは以下の記事にあります。
https://zenn.dev/akaneiy/articles/96398f179d8333

以下のようなコードでカスタム関数を作成します。

function geocoder(cell) {
   try{
      const response = Maps.newGeocoder().geocode(cell)
      if(response['results'][0] != null){
        return response['results'][0]['geometry']['location']['lat']+","+response['results'][0]['geometry']['location']['lng'];
      }
   }catch(e){
     return "error";
  }
}

これを実行してみます。

緯度経度を取得することができました。

3.kepler.glで可視化

1、2の流れで作成したダンダダンの店舗データをkepler.glを用いて可視化してみたいと思います。
kepler.glはUber社が提供している無料のGISツールです。

可視化してみると以下のようになりました。

黄色い点がダンダダンの店舗です。
明らかに関東に集中していることがわかります。

関東を拡大してみましょう。

点が都心を中心に放射状に広がっています。
東京における鉄道の広がり方と似ていますね。
ということは駅の近くにダンダダンは出店していると考察することができます。

試しに線路と駅も地図に載せてみましょう。

青い線が線路、水色の点が駅です。(国土数値情報より取得)
少しごちゃごちゃして見えますが、だいたい黄色い点が青い線の上に乗っていることがわかります。

もう少し拡大してみます。

こうみると中央線のほとんどの駅にダンダダンが出店していることがわかります。
(真ん中の横に真っ直ぐ伸びている線路が中央線です)

ダンダダンが出店している駅とその駅の乗降客数の関係はどうなっているのでしょうか。
2019年の乗降客数によって駅の点の大きさを変えてみます。

乗降客数の多い(点の大きさが大きい)駅の近くにダンダダンが出店していることがわかります。

当たり前ですが、居酒屋としては駅の近くでないと集客が見込めないので、乗降客数が多い駅の近くに出店したいですよね。乗降客数の多い中央線沿線に出店するのは必然と言えます。

東京にはだいぶ出店しているので、これからは神奈川、埼玉、千葉への出店に力を入れるんでしょうか。

いろんな居酒屋の店舗を地図上に並べて、出店戦略の違いを比べてみたいですね。

Discussion