WEBスクレイピング - 青山編 -
前回の記事ではpython + Beautiful Soupを使ってAOKIの店舗住所をスクレイピングしてみました。
今回は青山の店舗住所を抽出したいと思います。
作業環境は前回の記事と同様です。
青山の店舗検索ページ
青山の店舗検索ページ(https://www.y-aoyama.jp/shop/?lc=header)にアクセスし調べてみたところ、上の画像のように左上の都道府県欄にどこかの都道府県を指定しないと店舗情報が出てきませんでした。
上の画像では北海道を指定しており、
URLはhttps://www.y-aoyama.jp/shop/?pref=1
となっています。
?pref=
以下の数値が各都道府県と対応づけられているので、この数値を変えることで、全国の店舗名と住所を抽出できそうです。
ソースHTMLを見てみる
Google chromeの開発者ツールを使って見ていくと、
- 店舗名は、
<div class=” arrowTicket_body”>
→<h2>
の内部テキスト - 住所は、
<div class=” arrowTicket_body”>
→<p class=” arrowTicket_text arrowTicket_margin”>
の内部テキスト
であることが分かります。
以下のコードのようにfind_all()
とget_text()
を使って簡単に店舗名と住所(検索ページの最初に記載されている1店舗分ですが)を抽出することができました。
なお、get_text()
で得られた住所情報は、郵便番号と住所が混じっていためsplit()
を用いて分離しています。
#! python3 # -*- coding: utf-8 -*- import requests from bs4 import BeautifulSoup url = r'https://www.y-aoyama.jp/shop/?pref=1' res = requests.get(url) res.raise_for_status() soup = BeautifulSoup(res.content, 'html.parser') shop_elems = soup.find_all('div', class_='arrowTicket_body') # 店舗名 shop_name = shop_elems[0].h2.get_text() # 住所 shop_address_elem = shop_elems[0].find_all('p', class_='arrowTicket_text arrowTicket_margin') shop_address = shop_address_elem[0].get_text() # 郵便番号と住所を分離し保存 post_code = shop_address.split(None,1)[0] address = shop_address.split(None,1)[1]
コード内のshop_elems
はページ内の店舗情報が記載されているdiv要素のリストです。
ページ内の店舗情報を抽出する場合には、リスト内でループを回すことで取得できます。
全店舗の位置情報を取得するためのコード
上述のコードで店舗名と店舗住所が抽出できたので、それを基にfor文を使用して全店舗の情報を抽出していきます。
ソースコードを下に貼りました。流れは以下の通りです。
- 各都道府県のページに移動するために、都道府県ごとの店舗名と住所を取得しリストに保存。
- 既に閉店しているものを除外。
- 住所に
 
が入っているのを除外(文字化け対策)。 - 抽出した情報をCSVファイルに格納。
取得した住所情報には、既に閉店した店舗情報が入っており、それらは店舗名に「完全閉店」と書かれているので、リスト内包記とfilter関数を用いて閉店した店舗を除外しています。
また、住所に半角スペースの一種である  (0xA0)
が含まれており、本環境では文字化けするのでreplace()
を使用して除外しています。
以上で、AOKIと青山の店舗位置情報を得ることができたので、次回からQGISを用いて各店舗の位置関係を調べていきたいと思います。
#! python3 # -*- coding: utf-8 -*- import csv import requests from bs4 import BeautifulSoup # 店:青山(全国) # 変数prefは「都道府県」ドロップリストの並び順になっている模様 url = r'https://www.y-aoyama.jp/shop/' res = requests.get(url) res.raise_for_status() # 都道府県名とそのidを取得 soup = BeautifulSoup(res.content, 'html.parser') pref = [] pref_id = [] pref_elem = soup.find_all('option') for i in range(len(pref_elem)): pref.append(pref_elem[i].get_text()) pref_id.append(pref_elem[i]['value']) # 最初と最後に格納される'選択してください'を削除 pref = pref[1:-1] pref_id = pref_id[1:-1] # pref&pref_idを用いて各都道府県のページに移動し店舗情報の抽出 # 店舗名と店舗住所の抽出用パラメータの初期化 shop_list = [] shop_name = [] post_code = [] shop_address = [] shop_pref = [] # 都道府県ごとにループ for i in range(len(pref)): res_temp = requests.get(url+'?pref='+pref_id[i]) res_temp.raise_for_status() # 店舗名と店舗情報の抽出 soup_temp = BeautifulSoup(res_temp.content, 'html.parser') shop_elems = soup_temp.find_all('div', class_='arrowTicket_body') for shop_elem in shop_elems: shop_name.append(shop_elem.h2.get_text()) shop_address_elem = shop_elem.find_all('p', class_='arrowTicket_text arrowTicket_margin') post_code.append(shop_address_elem[0].get_text().split(None,1)[0]) shop_address.append(shop_address_elem[0].get_text().split(None,1)[1]) shop_pref.append(pref[i]) # 閉店している店舗があるためそれらを除外する shop_nameに'完全閉店'と書かれている。 close_shop_indexes = [i for i, x in enumerate(shop_name) if '完全閉店' in x] for close_shop_index in close_shop_indexes: shop_name[close_shop_index] = '' shop_address[close_shop_index] = '' shop_pref[close_shop_index] = '' shop_name = list(filter(lambda x:x != '', shop_name)) shop_address = list(filter(lambda x:x != '', shop_address)のみ) shop_pref = list(filter(lambda x:x != '', shop_pref)) #   を除外(いくつかの店舗の住所に含まれており文字化けする) shop_address = [x.replace('\xa0', '') for x in shop_address] # csvファイルに書き出し output_file = open('aoyama_all.csv', 'w', newline='') output_writer = csv.writer(output_file) for i in range(len(shop_name)): output_writer.writerow([shop_name[i], post_code[i], shop_address[i], shop_pref[i]]) output_file.close()