超初心者がサンマルクカフェの店舗情報をスクレイピングしてみた
はじめに
初投稿です。今回は北海道にあるサンマルクカフェの店舗情報をPythonでスクレイピングしてみました。具体的には、店舗名・住所・電話番号を抜き出します。
あまりキレイなコードではないかもですが、とりあえずスクレイピングできたので投稿してみました。もっと良いコードがあれば直しておきます。
スクレイピングをするにあたって、キノコードさんのYouTube動画を大いに参考にさせていただきました。ありがとうございます! 参考:https://www.youtube.com/watch?v=EYffrAY5CNI
想定する読者
自分と同じく超初心者で、「スクレイピングを初めてやってみよう!」という人向けに書いていきます。ちなみに私はPython触れ始めて1か月の文系大学生です。
環境
Python3.9.6 Windows10 version2004
コードエディタはVScodeを使いました。
いざ、スクレイピング!
まずはライブラリの準備
スクレイピングをする際にはいくつかライブラリをインポートする必要があります。
from bs4 import BeautifulSoup import requests import time import pandas as pd from os import error
Beautifulsoup・・・webサイトを解析するために必要。
requests・・・PythonからHTTP接続するために必要。
time・・・処理に一定の時間を置くために必要。これを使わないとサーバーに過重な負荷をかけてしまい、サイバー攻撃をしているとみなされる場合があります。
pandas・・・スクレイピングをしたデータをデータフレームにする(データをキレイな形にする)ために使用。
error・・・最後にcsvファイルに落とし込むとき、文字化け対策するのに使いました。
まだこれらのパッケージをインストールしていない人は上のコードを書く前にコマンドプロンプトから「pip install ○○(パッケージ名。今回であればbs4,requests,pandasなど)」と打ち込んでおきましょう。VScodeのターミナルに書いてもokです。
webページを読み込む
ここから、実際にスクレイピングをしていきます。今回は北海道のサンマルクカフェの店舗情報を取りたいのでそのリンクを変数urlとして指定しました。一番下の変数soupはウェブページ全体を抜き出していることを表します。
url = "https://www.saint-marc-hd.com/b/saintmarc/attr/?kencode=01&brand_type=CFE" r = requests.get(url) #指定したurlに接続 time.sleep(3) #3秒間隔を置く soup = BeautifulSoup(r.text,"html.parser") #webページのhtmlを解析
次に、ctrl+shift+Iでwebサイトの構造を見ます。こんな感じの画面になります。画面中央上にある矢印マーク(画像の赤丸部分)を押したあと、webページ上の任意の部分にマウスを合わせると、右画面のhtmlに対応部分が表示されます。
まず、店舗情報が書いてある部分全体を抜き出します。今回のwebページにはdivタグのclass=MapiTableWrapInnerのところが該当しそうです。
そして、さきほど抜き出したsoup(webページ全体)の中からfind関数を用いて上記の部分を抜き出します。
ここで注意したいのは「class」という言葉は「if」などと同じようにPythonで既に使用されているので(予約語)、「class」という名前の変数をつけることができません。そのため、以下のコードではclass_としています。
content = soup.find(class_ = "MapiTableWrapInner")
次に、店舗名が書いてあるブロックを探してみます。今回のwebページでは店舗名が書いてあるのはdtというタグのようなので、それを全部抜き出せば店舗名を抜き出せそうです。 ただ、get_dtはhtmlのコードもくっついてきてしまうようです。
#店舗名を全部抜き出したい=dtタグを抜き出す! get_dt = content.find_all("dt")
なので、店舗名のテキストだけ抜き出して、それをリスト化したいところです。
#店舗名をテキストだけ取り出し、それをリスト化する shop_names = [] for i in range(len(get_dt)): shop_name = get_dt[i].text shop_names.append(shop_name) print(shop_names)
これで、店舗名をテキストのみ抜き出して、リスト化することができました。 同じように、住所や電話番号を抜き出します。
#住所をテキストだけ取り出し、それをリスト化する get_address = content.find_all(class_ = "MapiInfoAddr") len(get_address) shop_addresses = [] for i in range(len(get_address)): shop_address = get_address[i].text shop_addresses.append(shop_address) print(shop_addresses) #電話番号をリスト化し、それをリスト化する get_tel = content.find_all("li") get_tel[1].text len(get_tel) shop_tels = [] for i in range(len(get_tel)): shop_tel = get_tel[i].text shop_tels.append(shop_tel) shop_tels
これで、店舗名・住所・電話番号を抜き出せました。 ここからはエクセルに落とすときにキレイな形になるようにする作業です。
#店舗名、住所、電話番号を辞書型にする result = { "店舗名" : shop_names, "住所" : shop_addresses, "電話番号": shop_tels } result #データフレームにする df = pd.DataFrame(result)
データフレームにできたら最後はcsvファイルに落とし込みます。
df.to_csv("309cafe-Hokkaido.csv",index=False,encoding="shift-jis",errors = "ignore") #shift-jisだとエラーが出てきてしまうので、それは無視する
encodingはWindowsの人はshift-jis、Macの人はutf-8にします。私はWindowsなので、encoding="shift-jis"としたのですが、errorsを指定しないとこんなメッセージが出てしまいました。
これは"\xa0"という文字を読み込めないよ!というメッセージです。これを無視して読み込めばよいとのことなので、errors="ignore"と指定してあげればきちんとコードが実行されます。csvファイルを開いてみると、きちんと文字化けなく、スクレイピングした情報も欠損なくきちんと表示されています。
以上で今回の記事を終わります。最後まで見てくださりありがとうございました!