【Python】Wikidata から世界遺産の GeoJSON をつくる

世界遺産の経緯度データを取得する方法について説明します。
まず背景になりますが、UNESCO のサイトにて経緯度データを含む世界遺産のデータが Excel などで公開されています(参考)。ただし、以下のような利用規約があります。
- 営利目的での配布は NG 。非営利であっても申請書を提出する必要がある。
- データを加工して配布することは NG。
というわけで、UNESCO のサイトから取得した世界遺産データを GeoJSON などの地理データに変換して Web 上で公開することは NG ととらえたほうが良さそうです。
そこで、Wikidata を使用します。Wikidata とは、Wikipedia 等に使用される公開データ群で、ライセンスは CC0(著作権なし)にあたるので、かなり自由に使うことができます(参考)。このデータを世界遺産に限定し、SPARQL で取得します。
Python がある程度使える前提として詳細は割愛しますが、具体的なコードは以下のようになります。標準ライブラリしか使っていないので、以下の Python を叩くだけです。
import requests
import json
import re
endpoint_url = "https://query.wikidata.org/sparql"
sparql_query = """
SELECT ?item ?itemLabel ?coordinate WHERE {
?item wdt:P1435 wd:Q9259.
?item wdt:P625 ?coordinate.
?item rdfs:label ?itemLabel.
FILTER(LANG(?itemLabel) = "ja")
}
"""
headers = {
"Accept": "application/sparql-results+json",
}
response = requests.get(endpoint_url, params={"query": sparql_query}, headers=headers)
data = response.json()
features = []
for result in data["results"]["bindings"]:
label = result["itemLabel"]["value"]
point_str = result["coordinate"]["value"]
match = re.match(r"Point\(([-\d.]+) ([-\d.]+)\)", point_str)
if match:
lon, lat = map(float, match.groups())
feature = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [lon, lat]
},
"properties": {
"description": label,
}
}
features.append(feature)
geojson = {
"type": "FeatureCollection",
"features": features
}
with open("unesco_world_heritage_ja.geojson", "w", encoding="utf-8") as f:
json.dump(geojson, f, ensure_ascii=False, indent=2)
print(f"GeoJSON generated with {len(features)} features.")
実際に作成した GeoJSON を使って、当サイトでは世界遺産の地図上可視化を行っています。トップページより「地名表示」と書かれたセレクトボックスを「世界遺産表示」に変更すると、このコードで取得した GeoJSON をもとに、MapLibre で世界遺産の位置を表示します。
ちょっと宣伝
当サイトは地図を使った海外旅ブログまとめサイトとなっています。トップページに地図がありますが、地名を押すと画像が開き、画像を押すと関連記事一覧(クリック数順)が開きます。記事数が多い国ほど赤く、地名もその国で記事が多い都市の文字が大きくなるようにしています。ぜひ覗いてみてください。
当サイトで海外旅ブログを執筆することも可能です(もちろん無料です)! また既にブログをお持ちの方も、当サイトからリンクを貼ることができるようになっています。パントレ開発部までお気軽にお問い合わせください。
パントレ開発部