美味しいお店を手軽に見つけたい

# こんなことありませんか
見知らぬ土地でご飯を探そう思ってスマホで検索してみたけど、、、

- 食べログだと一覧から高評価のお店を探すのって大変
- googleマップだと検索候補を一個ずつクリックしてレビュー見てみないといまいちわからない
- レビューサイトは否定的意見を書かないから本当に美味しいか分かりずらい

街中でスマホ取り出して美味しいお店探そうとしても、ぱっと見で高評価のお店は出てこなくて難しいですよね。
***現在地周辺で高評価のお店を知りたい！***
そんな時に便利なのがこのページで紹介する高評価のお店マップです。
# 何をするのか
スクレイピングによって[食べログの百名店](https://award.tabelog.com/hyakumeiten)で紹介されているお店の情報を収集します。
その情報をGoogleマイマップにインポートすることで高評価のお店マップを作成します。
*実行前に次章の「スクレイピングする前に」をよく読んで危険性について十分に理解してください。*
# スクレイピングする前に
Webからデータを取り出し、分析可能なデータにすることをスクレイピングといいますがいくつか注意点があります。
### 著作権に配慮すること
収集したデータに著作物が含まれていた場合は著作権に配慮しなくてはいけません。
スクレイピングで収集したデータを他人に渡す、収集したデータをもとにビジネスを始めるなどの行為はやめましょう。
一方で私的利用のための複製は認められているようです。
### データ取得先に過大な負荷をかけないこと
多くの場合、データの収集のためにはWebサーバに対しリクエストを複数回送信するかと思います。
短期間に大量のリクエストを送信するとWebサーバがパンクしてしまう可能性もあるので気を付けましょう。
過去には故意でなくても逮捕されるという事例がありました。
### 利用規約を確認すること
スクレイピングか禁止されていることもあるので利用規約はちゃんと読んでおきましょう。
またWebサイトにはrobots.txt という、クローラーを制御するためのテキストファイルが存在します。
このファイルの確認方法は割愛しますが、スクレイピングする前には対象Webサイトのrobot.txtを確認し、記載された内容に従うようにしましょう。
### 自分で安全性を確認すること
以上の注意点を簡単に説明しましたが、独自でまとめたものなので十分でない可能性が高いです。
自身で調査を行って問題がないことを確認してからスクレイピングしてください。
# 実装
実装にはpythonおよびそのライブラリであるBeautifulSoupを使用します。
これらはスクレイピングで最もメジャーで参考記事も多く、初心者にも扱いやすいため採用しました。

```python:main.py
import requests
from bs4 import BeautifulSoup
from time import sleep
import pandas

url = "https://award.tabelog.com/hyakumeiten/tonkatsu"
r = requests.get(url)

soup = BeautifulSoup(r.content, "html.parser")
shoplinks = soup.findAll('a', class_='list-shop__link-page')
rowdata = []
for shoplink in shoplinks:
    url = shoplink.get("href")
    rshop = requests.get(url)
    soup = BeautifulSoup(rshop.content, "html.parser")
    print("------------------")
    print(url)
    shopname = soup.find(
        "div", class_="rdheader-rstname").find("h2").find("span")
    print(shopname)
    if shopname is not None:
        shopname = shopname.get_text().strip()
    address = soup.find("p", class_="rstinfo-table__address")
    if address is not None:
        address = address.get_text()
    print(address)
    point = soup.find("span", class_="rdheader-rating__score-val-dtl")
    if point is not None:
        point = point.get_text().strip()
    print(point)
    regholiday = soup.find("dd", class_="rdheader-subinfo__closed-text")
    if regholiday is not None:
        regholiday = regholiday.get_text().strip()[0:10]
    print(regholiday)
    rowdata.append([shopname, address, point, regholiday, url])
    sleep(5)

print(rowdata)

df = pandas.DataFrame(
    rowdata, columns=["shopname", "address", "point", "regular holiday", "url"])
df.to_csv("tonkatsu" + ".csv", index=False)
```

このコードは百名店2019に対応しています。百名店2020を確認したところWebページの構成が変わっているためデータを取得できませんでした。

# 実行
実行はpythonをインストールし、このスクリプトを実行するだけです。
このコードを実行することで百名店に選ばれたとんかつ店のデータがcsvで取得できます。
餃子のデータを取得したい場合はurlの末尾をgyozaに、最終行のtonkatsuをgyozaに変更してあげれば大丈夫です。

# マイマップにインポートする
あとは生成されたcsvをGoogleのマイマップにインポートするだけです。
必要なジャンルのcsvをインポートしたら百名店がプロットされたマップが完成します。

# まとめ
このように、スクレイピングによって食べログ百名店で紹介されているお店の情報をデータとして抽出し、マップ化することができました。
マイマップはAndoroidで閲覧可能であるため、現在地から最も近い百名店を一瞬で見つけることが可能です。

# 課題
結構前に作ったスクリプトなんですが、改めて見てみるとpython初学者であることが全く言い訳にならないくらいの酷いコードですね、、、
本当はジャンルを実行時引数から取得できるようしたスクリプトがあるんですが公開をためらうレベルなので止めました。
以下が解決したらgithubで公開するかもしれません。

- 実行ファイル化
- ロギング
- urlを設定ファイルから読み込む
- HitchHiker's guide to pythonに基づくリポジトリ構成
- テスト
- 設計見直し


# 参考
https://docs.pyq.jp/column/crawler.html
https://www.cric.or.jp/qa/hajime/hajime8.html
https://ja.wikipedia.org/wiki/%E5%B2%A1%E5%B4%8E%E5%B8%82%E7%AB%8B%E4%B8%AD%E5%A4%AE%E5%9B%B3%E6%9B%B8%E9%A4%A8%E4%BA%8B%E4%BB%B6