ぴょこりんブログ

裏垢です。

立ち食いステーキはフィットネスとともに。

この記事は、またまた!ぴょこりんクラスタ Advent Calendar 2017のために書きました。

はじめに

アメリカっぽいことを書きますって予告したんですけど、アメリカを日本でも満喫したいですよね(?????)。アメリカといえばやっぱりアレですよ、肉、あと筋トレ。

グローバルエリートたちは肉を食らい、そして日々筋トレをして己を高めているワケですね。そういう生活、日本でもしたいですよね、もちろんしたいですよね。日本だったらどこでも良いわけじゃない、もちろん東京でしたい!!!!!!!

ちょっと前に話題になってたやつ。 g-topi.com

いやこれすごく良いですよ。すぐ近くにいきなり!ステーキとエニタイムフィットネス、僕はめっちゃ良いと思うんですよ。池袋界隈の人々だけにこんないい思いを!!!!悔しい!!!!!!!!

というわけでね、今日はね、圧倒的ビッグデータの力でね、見つけちゃう。知られざる永久機関たちを。そういうやつです。

やったこと

エニタイムフィットネスさんのサイトといきなり!ステーキさんのウェブサイトから住所の情報をスクレイピングして、その住所をgoogle mapのAPIにぶん投げて緯度経度を取得、緯度経度から距離を測って、互いに近傍に存在するエニタイムフィットネス店舗といきなり!ステーキ店舗のペアを見つける、簡単でしょ?あ、もちろん僕はpythonしかかけないのでpythonでやりました。そこら辺の詳細はめんどくさいので割愛します。

スクレイピング

朝飯前っすね、BeautifulSoupは朝でも胃に優しい。

エニタイムフィットネスは各店舗それぞれにページがあるので、全体からそのリンクを取得して、各ページにアクセス、記述されてる店舗名と住所を取得しています。

import urllib
from bs4 import BeautifulSoup as bs

def link2address(link):
    tmp=urllib.request.urlopen('https://www.anytimefitness.co.jp'+link)
    return bs(tmp.read(),"html5lib").find('p',{'class':'address'}).contents[2].strip()

tmp=urllib.request.urlopen('https://www.anytimefitness.co.jp/list/')
test=bs(tmp.read(),"html5lib").findAll('li')
fitness_list=[(i.p.contents[0],link2address(i.a['href'])) for i in test if i.a!=None]

次にいきなりステーキ、東京のページが一つにまとまってたので、そこから店舗名と住所をぶっこ抜くのみ。 なんとなく全角スペースが気になったので半角に置換している。

tmp=urllib.request.urlopen('http://ikinaristeak.com/shopinfo/?area1=%E6%9D%B1%E4%BA%AC%E9%83%BD')
test=bs(tmp.read(),"html5lib").findAll('div',{'class':'data'})
steak_list=[(i.h3.contents[0].replace('\u3000',' '),i.p.contents[2].strip().replace('\u3000',' ')) for i in test]

どちらも、(店舗名、住所)ってタプルのリストになっています。 何も考えてないと雑に変数にtmpとかtestとかつけてるのよくないっすねー。

緯度経度情報の取得

googlemapsを使います。pip install googlemapsでさくっと入ります便利。 取得済だったのでgoogleAPIキー入れたけどもしかしたら不要かも(未確認)。

import googlemaps

gmaps = googlemaps.Client(key='ここにAPIキーを入れてね!')
def address2latlng(address):
    address=address.split(' ')[0] # 建物名が入ってるとたまに取れないので
    geocode_result = gmaps.geocode(address)
    return geocode_result[0]['geometry']['location']['lat'],geocode_result[0]['geometry']['location']['lng']

fitness_latlng=[i+address2latlng(i[1]) for i in fitness_list]
steak_latlng=[i+address2latlng(i[1]) for i in steak_list]

建物の名前が住所に入ってるとたまに緯度経度取れずコケることがあるので、住所の最初のスペース以前のみを入力にしてビル名は捨ててます。

距離の計算

そもそもgoogle mapに住所から2点間の距離を算出するAPIがありそうな感じだったのだけれど、流石に(いきなりステーキ店舗数)✕(エニタイムフィットネス店舗数)はAPI上限(2500回)超えそうだったので断念。緯度経度からの2点間距離を測る方法として、ヒュベニの公式というのが使えるそうなので、愚直にこれに当てはめてみましょう。

import math
a=6378137.000
b=6356752.314245
e=((a**2-b**2)/a**2)**0.5

def distance(y1,x1,y2,x2):
    x1=math.pi*x1/180.
    x2=math.pi*x2/180.
    y1=math.pi*y1/180.
    y2=math.pi*y2/180.    
    dy=y1-y2
    dx=x1-x2
    muy=(y1+y2)/2
    W=(1-(math.sin(muy)*e)**2)**0.5
    M=a*(1-e**2)/W**3
    N=a/W
    
    d= ((dy*M)**2+(dx*N*math.cos(muy))**2)**0.5
    return d

これで距離が計算できるようになりました。やっぱ距離は近い方が良いっすよね、妥協しても300m以内とかそれくらいでしょ。

import itertools
distances=[(i[0][0],i[1][0],distance(i[0][2],i[0][3],i[1][2],i[1][3]))\
 for i in itertools.product(fitness_latlng,steak_latlng)]

print([i for i in distances if i[2]<300])

で結果が、

[('赤坂店', '赤坂サカス店≪2016期間限定≫', 153.41865068249004),
 ('赤坂店', '赤坂サカス店≪期間限定≫ 2015 ', 34.36660561722682),
 ('赤坂店', '赤坂通り店', 205.6565613111345),
 ('曙橋店', 'あけぼのばし店', 76.31203432319411),
 ('東新宿店', '大久保店', 126.65032605674229),
 ('亀戸店', '亀戸駅前店', 270.2350739647668),
 ('門前仲町店', '門前仲町店', 276.4330947716838),
 ('学芸大学店', '学芸大学店', 289.51438585200407),
 ('大森駅前店', '大森ララ店', 202.70278377365887),
 ('蒲田店', '蒲田店', 91.20711350384839),
 ('三軒茶屋店', '三軒茶屋店', 103.92844433335154),
 ('恵比寿店', '恵比寿店', 291.1489173613131),
 ('高円寺店', '高円寺南口店', 131.86806925073424),
 ('池袋店', '池袋西口店', 0.0),
 ('王子店', '王子店', 0.0)]

(エニタイムフィットネスの店舗名、いきなりステーキの店舗名、距離)のタプルのうち、距離が300m未満のものを列挙しています。東京のいきなりステーキしか入れてないので結果は東京のものだけです。どうでもいいですが毎年赤坂サカスでいきなりステーキは期間限定店舗を出しているんですね。

そしてご存知の通り永久機関と呼ばれてる池袋、距離0と出てますね、いい感じです。更に驚くべきことにもうひとつ、なんと王子にも永久機関があるじゃないですか。ストリートビューで確認してみましょう・・・。

f:id:cappsLk:20171205203857p:plain

永久機関だ!!!!!しかし実用面では新宿とか恵比寿とか、それこそ池袋とかの方が良さそうですね。

まとめ

永久機関を探したところ、王子にもあった。同じビルではないけどそこそこ近いペアもいくつかあった。

おしまい。

あ、僕はいきなり!ステーキさん、及びエニタイムフィットネスさんが大好きです!