【Python】アメリカの空港を表示
2020年12月7日
Latitude and Longitude Finder
のサイトから、アメリカの空港の座標をスクレイピングで取得して、leaflet上に表示させてみます。
Flaskを使って、Webアプリケーションとしました。
app.pyファイルです。
from flask import Flask, redirect, render_template
from urllib.request import urlopen
from bs4 import BeautifulSoup
import json
import csv
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# URLの指定
html = urlopen("https://www.latlong.net/category/airports-236-19.html")
bsObj = BeautifulSoup(html, "html.parser")
# テーブルを指定
table = bsObj.findAll("table")[0]
rows = table.findAll("tr")
data = []
# Flaskインスタンス
app = Flask(__name__)
# URLのルーティング
@app.route('/')
def index():
with open("data.csv", "w", encoding='utf-8') as file:
writer = csv.writer(file)
for row in rows:
csvRow = []
for cell in row.findAll(['td', 'th']):
csvRow.append(cell.get_text())
data.append(csvRow)
writer.writerow(csvRow)
json_list = []
# CSV ファイルの読み込み
with open('data.csv', 'r') as f:
for row in csv.DictReader(f):
json_list.append(row)
# JSON ファイルへの書き込み
with open('output.json', 'w') as f:
json.dump(json_list, f)
# JSONファイルのロード
with open('output.json', 'r') as f:
json_output = json.load(f)
# htmlのレンダリング
return render_template('osm_map.html', data = json_output)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
osm_map.htmlファイルです。templatesフォルダに保存します。
<!DOCTYPE html>
<html><head><meta charset="UTF-8">
<link
href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
rel="stylesheet" />
<script
src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
type="text/javascript"></script>
</head>
<body>
<div id="map_div" style="width: 1200px; height: 600px"></div>
<script type="text/javascript">
let list_data = JSON.parse('{{ data |tojson|safe }}');
const defPos = [list_data[0].Latitude, list_data[0].Longitude]
const copyright = "© <a href='" +
"https://www.openstreetmap.org/copyright" +
"'>OpenStreetMap</a> contributors"
const map = L.map('map_div').setView(defPos, 3)
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{ attribution: copyright}
).addTo(map)
for(let i=0;i<list_data.length;i++){
const defPos = [list_data[i].Latitude, list_data[i].Longitude]
const marker = L.marker(defPos).addTo(map)
}
navigator.geolocation.watchPosition(
function (pos) {
const lat = pos.coords.latitude
const lng = pos.coords.longitude
const zoom = map.getZoom()
map.setView([lat, lng], zoom, {animation: true})
marker.setLatLng([lat, lng])
})
</script>
</body>
</html>
以下を実行します。
$ python app.py
こんな感じにインタラクティブな地図が表示されます。