完全禁煙のカフェを現在地から簡単に調べるサイトを作った件

外出先で完全禁煙のカフェを探す手間を最小限にするため、ブラウザで開くだけで現在地から周辺にある禁煙のカフェやレストランの存在を簡単に調べられるサイトを作ったという話。

仕事でお客さんのところに往訪したりすると、たまに次の予定との間に中途半端に時間が空いてしまうこととかあります。そういう時ってちょっとカフェでも入って休憩しようかなってなるんですけども、

  • いちいち地図アプリ開いて「カフェ」とか検索するのダルい
  • 検索して出てきたカフェが完全に禁煙のお店か調べるのが面倒くさい (私、タバコ吸わないので)

という 2点が以前から気になっていまして。

それなら Web ページ開くだけで周辺にある完全禁煙のカフェを探せるサイトを自分用に作っておけばいいじゃんということで、週末にささっと作ってみたのですが、自分以外にも役に立つ人もいるかなということで公開してみます。

実際に作ったサイト

ということで作ったサイトが下記。

私が仕事でうろちょろするのは東京都内のみなので、データも都内のみ限定です。なので他のエリアで上記のページを開いても意味ないですからご了承ください。

実装方法

実装的には Geolocation API でブラウザから現在地を取得、裏側で別途作成した店舗データを XML で書き出し、Maps JavaScript API を利用して Google Maps 上に表示しているという単純なものです。

自分用に作ったのでデザインも適当...... というかしてないですし、マーカーもいちいち作るの面倒だったので標準マーカーに マーカーラベル で店舗カテゴリの頭文字を入れただけの単純なものです。

動作的にはブラウザで、位置情報の利用を許可した状態で Web サイトを開くと、現在地の情報を取得し、そこを中心に地図とマーカーを描写します。例えば私は iPhone ユーザーなので、このページをホーム画面に保存しておけば、ワンタップで今いるところの周辺にある完全禁煙のカフェを探すことができますと。

実際に何度か仕事の合間に使ってある程度役に立ってるのでまぁいいかなといったところ。

禁煙店舗のデータ抽出

登録されている 「禁煙」 の店舗は下記の通り抽出しました。

  • 食べログさんで「東京都内」の「禁煙」「カフェ」を検索
  • スターバックスの東京都内店舗(基本的にテラス席以外は禁煙という前提で全店舗)
  • タリーズコーヒーの東京都内店舗のうち「完全禁煙」となっている店舗
  • ドトール(エクセシオール カフェ含む)の東京都内店舗のうち「完全禁煙」となっている店舗
  • 上島珈琲店の東京都内店舗のうち「完全禁煙」となっている店舗
  • カフェ・ベローチェの東京都内店舗のうち「完全禁煙」となっている店舗のみ、14店舗

食べログに関しては検索結果のページを辿りつつ、掲載されている店舗個別ページをまずはスクレイピングして取得し、その後、各ページから 「店舗名」「住所」「ページの URL」 をスクレイピングして CSV ファイルにまとめます。

で、ページのどこからデータを抜くかですが、ページのソースコードみてたら 「メールで情報を送る」 ってボタンにいい感じに店舗名、住所、個別ページの URL がまとめて入っていたのでそこから引っこ抜く感じでスクレイピングしたら比較的楽にいけました (ちなみにやってて気がついてしまったんですが、店舗名や住所内に 「&」 が入ってる場合にエスケープされてないみたいでいくつか取得したデータがおかしい店舗がありました...... 食べログさん直した方がいいかも)。

その他カフェチェーン店に関しては各公式 Web サイトの店舗検索ページから必要な情報を取得します。

ちなみにスタバは東京都内の店舗を全取得するだけだったので簡単。タリーズコーヒー以外は検索条件で 「完全禁煙」 を指定できたのである程度簡単に取得できましたが、タリーズコーヒーだけは公式サイトの検索で禁煙の店舗が探せないっていうクソ(ゲフン...... もとい、少しだけ手がかかる仕様だったため、食べログ等での検索も交えてちょっとだけ手がかかりました。

とはいえ、タリーズコーヒーさんは基本的に喫煙可能な店舗でも分煙がきちんとされているみたいなので、完全禁煙じゃなくても、明確に分煙さえされていればいいよって人には全店舗、全く問題ないとも言えるかもしれませんけども(一応フォローしておく

住所から位置情報の取得

で、この Web サイトは裏で WordPress を動かしてまして、データの管理だけしていますが、上記で集めた店舗データ (CSV) を、WordPress にインポートします。

その際、「Advanced Custom Fields」 を使用してあらかじめ 「_address」「_lat」「_lng」 というカスタムフィールドを作成しておき、CSV からとりあえず下記のようにフィールドにデータが入るようにします。

  • post_title(タイトル)→ 店舗名
  • _address(カスタムフィールド)→ 住所

当然、記事のインポートが完了した時点では各記事の 「_lat」「_lng」 フィールドは空です。

店舗の位置情報は、入力した住所データから、「Google Maps Geocoding API」 を利用して取得するようにします。

位置情報の取得は WordPress さんにやらせようということで、記事の公開 or 更新時に 「_lat」「_lng」 フィールドが空だった場合に、API にアクセスして 「_address」 に入っている住所から位置情報を取得し、「_lat」「_lng」 各フィールドにデータを入れる関数を functions.php に追加します。具体的には下記のような感じ。

<?php
 
/**
 * Google Maps Geocoding API
 */
 
add_action('wp_insert_post', 'geocoding');
function geocoding($post_ID) {
  $post = get_post($post_ID);
 
  // 「_lat」「_lng」 フィールドが空の時だけ実行
  if(get_post_meta($post->ID, '_lat', true) == '' && get_post_meta($post->ID, '_lng', true) == ''){
 
    // API キーとかリクエスト先の設定とか
    $key        = "__API_Key__";
    $googleapis = "https://maps.googleapis.com/maps/api/geocode/json";
    $address    = urlencode(mb_convert_encoding(get_post_meta($post->ID,'_address', true), 'UTF-8', 'auto'));
    $url        = $googleapis . '?address=' . $address . '&key=' . $key;
 
    // curl で JSON を取得して必要な情報を取り出す
    $ch = curl_init();
    $options = [
      CURLOPT_URL => $url,
      CURLOPT_HEADER => false,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_TIMEOUT => 3
    ];
    curl_setopt_array($ch, $options);
    $json = curl_exec($ch);
    curl_close($ch);
 
    $geocoding_data = json_decode($json, true);
 
    $lat    = $geocoding_data['results'][0]['geometry']['location']['lat'];
    $lng    = $geocoding_data['results'][0]['geometry']['location']['lng'];
    $status = $geocoding_data['status'];
 
    // フィールドに値を入力
    if($status == 'OK'){
      update_post_meta($post->ID, '_lat', $lat);
      update_post_meta($post->ID, '_lng', $lng);
    }
  }
}
 
?>

WordPress とか PHP を久しぶりに触ったので間違いがないかちょっとだけ心配ですが、まぁきちんと動いているのでいいかなと。

まとめ

  • 外出先で禁煙のカフェだけ簡単に探したかったのでそういう Web サイト作りました。名前は「禁煙店舗」(そのまんま
  • Google Maps JavaScript API を使用した簡単な仕組み
  • データは食べログさんなどからスクレイピングして集めさせていただいたもの。ただ、「完全禁煙」 でデータを集めても、一部には加熱式タバコは OK とか、分煙の店が混ざっている可能性もあるのでその辺の細かいことは気にしない
  • 自分が使うようなので都内のデータしか入力していないです
  • 裏側は WordPress を使ってみました
  • 集めた店舗住所から地図上でのマーカー表示に必要な位置情報の取得は Google Maps Geocoding API を利用
  • Google Maps JavaScript API の使用制限 (マップのロードが 24 時間あたり 25,000 回以内) があるけど、まぁ余程のことがない限り大丈夫でしょ

ということで、かなり雑な感じではありますが簡単に紹介してみました。

余談ですが、去年からしばらくこの Blog の更新サボってましたらお会いした方にブログ書いてないっすね的なこと言われたりしたので、たまには Blog 書かないとと思ったんですけども最近長文を書くのが億劫になってしまいましてね...... 書こうと思ったネタだけ溜まって賞味期限が切れていくという状態になっております。