Python
GoogleMapsAPI
Python3
BeautifulSoup
folium

旅行情報サイトをスクレイピングし、地図上にプロットする

目的 

今回は、スクレイピングの練習のために旅行情報が載っているRETRIPの注目のまとめにある記事を一つ一つ探り、位置情報と場所の名前を取得し、地図上にプロットすることで取り上げられるスポットの地理的偏りなどがあるのかどうかを可視化したいと思います。

スクレイピング

まずは、BeautifulSoupを用いて情報を取得します

from bs4 import BeautifulSoup
import requests
import re
import time
#urlを指定
url = 'https://retrip.jp/'

#情報を取得します

r = requests.get('https://retrip.jp/')
soup = BeautifulSoup(r.content, 'html.parser')

#1面から見るべきurlをリストにまとめる

urls = [url + i.get('href') for i in soup.find_all('a', href=re.compile('^/articles/')) ]

shop_place_dic = {}

for url1 in urls:
   #入ったurlの中にさらにページ分けされているので何ページあるか確認
    r1 = requests.get(url1)
    soup1 = BeautifulSoup(r1.content, 'html.parser')

    add_urls = []
    for i in soup1.find_all('a', class_='page'):
        add_urls.append(i.get('href'))

    urls2 = [url1]

  #ページ全て回れるようにリスト作成

    for i in add_urls:
        urls2.append(url1 + i)

    for url2 in urls2:

        #攻撃にならないようにsleepしつつ取得しましょう

        time.sleep(1)
        r2 = requests.get(url2)
        soup2 = BeautifulSoup(r2.content, 'html.parser')

        for j in soup2.article.find_all('div', class_='expSpotContent'):
            shop_place_dic[j.a.text] = j.li.text

さあ、これで辞書型のキーに名前、バリューに場所が入った結構な長さの辞書が得られます。
注目のまとめは640ページ分ありますが今回は1ページ分にしておきます。

プロット 

さて、得られた位置情報をもとに地図にプロットするためにGoogle Maps APIを用いてジオコード化します。
そして、それをもとにfoilumを用いれば簡単にプロットできます。

import requests
import json
import folium
from time import sleep

wait_time = 0.3 # (sec)

#key以下に自分のAPI Idを入れましょう

address_url = 'https://maps.googleapis.com/maps/api/geocode/json?address='
key_url = '&key="""YOUR API IDs"""'
headers = {'content-type': 'application/json'}

#適当に初期設定

map1 = folium.Map(location=[ 35.9586186, 139.4288445], 
                      zoom_start=6)

coordinates = {}

#前で作った辞書からすべてをジオコード化します

for k, v in shop_place_dic.items():
    v = v.strip()
    url = address_url + v + key_url
    r = requests.get(url, headers=headers)
    data = r.json()
    if 'results' in data and len(data['results']) > 0 and 'formatted_address' in data['results'][0]:
        coordinates[k] = [data['results'][0]['geometry']['location']['lat'],
            data['results'][0]['geometry']['location']['lng']]
    else: continue

  #APIの使用制限があるのでsleepしつつ

    sleep(wait_time)

    #これで地図にマーキング

    folium.Marker(coordinates[k], 
                  popup = k).add_to(map1)

#保存

map1.save('./map.html')

このように地図上に全てプロットすることができました。
(見にくくてすいません)
ちなみに、ピンをクリックすると、場所の名称が出て来るようにしてあります。
スクリーンショット (4).png

課題

コードが汚いですよね。なにか工夫できる点を探したい。

こちらを参考にすればもっとおもしろい地図データを書けそう

<追記>
スポットの種類による、ピンの色わけ、クリックする事によるurlへのジャンプが実装可能であるようだ。