7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

KDDI EngineerAdvent Calendar 2020

Day 4

指定した都道府県にあるコンビニの住所を取得し、Google Mapで表示してみた[beautifulsoup4編]

Last updated at Posted at 2020-12-03

はじめに

  • こんにちは ! KDDI アジャイル開発センターの小板橋です。
    今回は、scrapyを利用した面白いスクレイピングツールを拝見したため、僕はそれをbeautifulsoup4で再現してみました。

  • 内容としては、beautifulsoup4を利用し、NAVITIMEをスクレイピングし、指定した都道府県のコンビニ(セブンイレブン、ローソン、ファミリーマート)の住所を取得し、GCPのgeocoding apiを利用し緯度経度に変換後CSV出力するといったものです。

beautifulsoup4とは

beautifulsoup4とは、HTMLやXMLから欲しいデータを抽出するためのPythonライブラリです。

インストール方法
pipでインストールできます。

 pip install beautifulsoup4

BeautifulSoupでHTMLの中からHTML要素を取得するには、下記の2タイプのメソッドを使用します。

  • find系 find_all()、find()
  • select系 select()、select_one()

今回は、find系のfind_all()を使用しました。

ちなみに、上記のfind系とselect系の違いなのですが、

種類 すべての要素をリストで返却 ひとつだけ要素を返却 引数
find系 find_all() find() 要素名,属性指定
select系 select() select_one() CSSセレクタ

geocoding apiとは

住所を地理座標(緯度/経度)に変換できるAPIです。

インストール方法
pipでインストールできます。

pip install googlemaps

実装

注意点: For文の最大値を下記のコードでは東京都のセブンイレブンを検索時の最大ページ数にしている
→ 引数で得たコンビニを検索時のページ最大数を取得する修正をしようとして、力つきました。笑

google_map_scraping.py

#!/usr/bin/env python
from urllib import request, error
from bs4 import BeautifulSoup
import csv
import googlemaps
import time
import sys
from argparse import ArgumentParser, FileType

storepath = '0201001001'
citypath = '13'

def gettext():
    response = request.urlopen(url)

    try:
        with request.urlopen(url) as res:
            res.read()
    except error.HTTPError as err:
        print(err.code, "wwwww")

    soup = BeautifulSoup(response, 'html.parser')
    response.close()
    csvRow = []

    googleapikey = '個人のGoogelMapのAPIkeyを設定'
    gmaps = googlemaps.Client(key=googleapikey)

    for i in soup.find_all(class_="ellipsis"):
        i.extract()

    for j in soup.find_all(class_="spot-detail-value-text"):
            texts = j.get_text()
            csvRow.append(texts.strip())

    with open("store_lat_lng.csv", "a", encoding='utf-8') as file:
        for csvRows in csvRow:
            result = gmaps.geocode([csvRows])
            if len(result) != 0 :
                lat = result[0]["geometry"]["location"]["lat"]
                lng = result[0]["geometry"]["location"]["lng"]
                writer = csv.writer(file)
                writer.writerow([csvRows, lat, lng])
                time.sleep(0.5)
    print("終了")
    sys.exit()

p = ArgumentParser(description='指定した都市におけるコンビニの緯度経度をCSVとして吐き出す')
p.add_argument('--store', choices=['セブンイレブン', 'ローソン', 'ファミリマート'], default='セブンイレブン', help='default=セブンイレブン')
p.add_argument('--city', choices=['tokyo', 'Kanagawa', 'Osaka'], default='tokyo', help='default=tokyo')
args = p.parse_args()
if args.store == 'セブンイレブン' :
    storepath = '0201001001'
if args.store == 'ローソン' :
    storepath = '0201001009'
if args.store == 'ファミリマート' :
    storepath = '0201001006'
if args.city == 'tokyo' :
    citypath = '13'
if args.city == 'Kanagawa' :
    citypath = '14'
if args.city == 'Osaka' :
    citypath = '27'


url = 'https://www.navitime.co.jp/category/{0}/{1}'.format(storepath, citypath)
gettext()
for i in range(2, 60):
    url = 'https://www.navitime.co.jp/category/{0}/{1}/?page={2}'.format(storepath, citypath, i)
    gettext()

動作

--helpで引数を確認

~/Desktop
❯ ./遊び用Pythonツール/google_map_scraping.py --help
usage: google_map_scraping.py [-h] [--store {セブンイレブン,ローソン,ファミリマート}]
                              [--city {tokyo,Kanagawa,Osaka}]

指定した都市におけるコンビニの緯度経度をCSVとして吐き出す

optional arguments:
  -h, --help            show this help message and exit
  --store {セブンイレブン,ローソン,ファミリマート}
                        default=セブンイレブン
  --city {tokyo,Kanagawa,Osaka}
                        default=tokyo

~/Desktop
❯

Defaultの値で実行

~/Desktop
❯ ./遊び用Pythonツール/google_map_scraping.py
終了

CSVを確認

store_lat_lng.csv
東京都三鷹市新川6-3-14,35.68321359999999,139.5685815
東京都千代田区永田町2丁目2番1号,35.6745788,139.743009
東京都港区六本木3-2-1,35.6645869,139.7377776
東京都八王子市高尾町1806-1,35.6333012,139.2562665
東京都世田谷区玉川3-11-7,35.6136912,139.6256771
東京都世田谷区太子堂2-12-1,35.6450583,139.6735356
東京都大田区東海3丁目2番1号,35.5789543,139.7591679
東京都目黒区下目黒5-18-21,35.6306158,139.7021458
東京都町田市鶴間8丁目15番21号,35.5103597,139.4769608
東京都千代田区九段南3-1-1,35.692245,139.7434825
東京都福生市熊川1411-6,35.7253801,139.3431771
東京都中央区新川2-27-2,35.6742508,139.7843206
東京都中央区日本橋箱崎町22-1,35.6815297,139.7862889
東京都新宿区中落合3-1-3,35.7223184,139.6919351
東京都新宿区新宿2-6-4,35.6900244,139.7071167
東京都新宿区西新宿6-5-1,35.6931766,139.6931655
東京都八王子市石川町2441-5,35.6739094,139.363978
東京都八王子市戸吹町1469-1,35.70595,139.2971229
・
・
・

Google Mapで表示してみた

1.Google Mapで[マイプレイス]を選択します。

スクリーンショット 2020-11-30 23.56.11.png

2.[地図を作成] → [インポート]を選択し、先ほどのPythonツールで出力したCSVを読み込ませる。
その後、列の緯度/経度をしていると一括で、表示される

スクリーンショット 2020-11-30 23.58.19.png

多いですね。。w

おわり

注意点としては、geocoding apiの使用料ですかね、1000リクエストで$5なので、お金のない僕としてはきついですw

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?