LCL Engineers' Blog

バス比較なび・格安移動・バスとりっぷを運営する LCLの開発者ブログ

日本の観光資源データを可視化してみた

イントロダクション

LCLエンジニアチームの杉山です。自分が仕事をさせて頂いている、株式会社LCLは旅人をふやす会社をミッションの一つとして、 バス比較なび、バスツアー、格安移動、海外航空券等のサイトにて情報を掲載して、サービス利用者の皆様へ最適なツアーや交通手段を手頃な値段で探す為の、 お手伝いをさせて頂いています。現状では、情報提供のみで旅行業の登録はしておりませんが、会社では年1回の旅行業務取扱管理者の資格取得をサポートしています。 提携先には運送・旅行関係の企業も多い為、旅行業界の知識を知っておくと、旅行業法的な観点以外にも、データ連携する時に航空券・JR路線(新幹線・在来線)・船舶・貸し切りバス等の データの意味を読み解く時にも理解し易いので、エンジニア職であっても知識として持っておいて損は無いかと思っています。

新幹線の料金は、本州3社、JR四国、JR九州、JR北海道などに跨る場合は、改札を出ずに同一方向に乗り継いでも、会社によって特急料金を通算出来なかったり、特定の駅で乗り換えないと新幹線と在来特急を乗り継いだ場合の5割引が効かなかったり。良く利用している、東海道新幹線の「のぞみ・みずほ」で普通車自由席を利用する場合は、「ひかり・こだま」の自由席特急料金が適用されたりと、普段業務としていないと知ることが出来ない事ばかりでした。また、定められた基準資産と営業保証金が用意出来れば、地域限定旅行業か第三種旅行も自分で起業する事も出来ますね。

国内旅行業務取扱管理者の勉強するにあたり、一番大変だったのは国内観光地・世界遺産・温泉等の観光資源を覚えるのが一番難易度が高いという印象でした。シンプルに暗記すれば良いのですが、どの都道府県にあるのか?どのような場所にあるのか?等。そこで、今回は国土交通省から提供されている観光地のデータをもとに各観光資源を地図上に可視化出来る環境を作成してみました。機能的にはまだまだ不足していますが、これから時間がある時に定期的に改良して活用頂けるような状態まで持って行ければなと考えてます。

環境 (WLS Ubuntu 20.04.3 LTS)

  • OS
DESKTOP-8B:$ sudo lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:        20.04
Codename:       focal
  • Docker
DESKTOP-8B:$ docker --version
Docker version 20.10.11, build dea9396

DESKTOP-8B:$ docker-compose --version
docker-compose version 1.16.1, build 6d1ac21

観光地データ

国土交通省(観光資源データ)

備考: 2021年夏に、「北海道・北東北の縄文遺跡群」や「奄美大島、徳之島、沖縄島北部及び西表島」等が新規に世界遺産に登録されました。

アウトプット

観光地リスト
東京駅から±630km : Geohash:xn
参照:GoogleマップGoogle マップ

基本データの取り込み「PostgreSQL、MySQL」

先ず最初に可視化する対象となるデータを、ShapeFileからデータベースに取り込んで行きます。 Shapefileの詳細に関しては以下参照ください。

シェープファイル (英語: Shapefile) は、 地理情報システム(GIS)間でのデータの相互運用におけるオープン標準として用いられるファイル形式である。例えば、井戸、川、湖などの空間要素がベクター形式であるポイント、ライン、ポリゴンで示され、各要素に固有名称や温度などの任意の属性を付与できる。

参照:Wikiシェープファイル ja.wikipedia.org

PostgreSQL (PostGIS)の場合

こちらは、LCLでも標準データベースとして利用している、オープンソースのPostgreSQLでの取り込み方法になります。

❶ PostgreSQLの起動

DESKTOP-8B:~/git/rdbms-docker/postgresql$ docker-compose -f ./docker-compose-with-postgis.yml up -d
Creating network "postgresql_default" with the default driver
Creating volume "postgresql_postgis-store" with default driver
Creating postgresql_postgres_1 ...
Creating postgresql_postgres_1 ... done
DESKTOP-8B:~/git/rdbms-docker/postgresql$ docker-compose ps
        Name                       Command              State                    Ports
--------------------------------------------------------------------------
postgresql_postgres_1   docker-entrypoint.sh postgres   Up      0.0.0.0:5432->5432/tcp,:::5432->5432/tcp

❷ ShapeFileのダウンロード
※ ここでは、東京の観光資源のデータのみを流し込んでいます。

DESKTOP-8B:~/win/GIS$ unzip ~/win/GIS/P12-14_13_GML.zip
Archive:  /home/shinya/win/GIS/P12-14_13_GML.zip
  inflating: KS-META-P12_14-13.xml
  inflating: P12-14_13.xml
  inflating: P12a-14_13.dbf
  inflating: P12a-14_13.prj
  inflating: P12a-14_13.shp
  inflating: P12a-14_13.shx
  inflating: P12c-14_13.dbf
  inflating: P12c-14_13.prj
  inflating: P12c-14_13.shp
  inflating: P12c-14_13.shx
DESKTOP-8B:~/win/GIS$

❸ Host OSにpostgis関連のコマンドのみインストール
※コンテナ側でもインストールは可能ですが、ここではシンプルな方法を選んでいます。

DESKTOP-8B:~/git/rdbms-docker/postgresql$ sudo apt install postgis --no-install-recommends

参照:Install only commandline tools

➍ shp2pgsqlにてShapeFileをデータベースに取り込む為のSQLに変換

DESKTOP-8B:~/win/GIS$ shp2pgsql -s 4326 -D -i -I -W SJIS P12a-14_13.shp > kanko_point_tokyo.sql
Shapefile type: Point
Postgis type: POINT[2]

DESKTOP-8B:~/win/GIS$ file kanko_point_tokyo.sql
kanko_point_tokyo.sql: UTF-8 Unicode text

➎ 対象スキーマにてEXTENTIONを有効化

DESKTOP-8B:~/win/GIS$ psql -h 127.0.0.1 -p 5432 -U postgres POC
Password for user postgres:
psql (13.5 (Ubuntu 13.5-2.pgdg20.04+1), server 13.4 (Debian 13.4-4.pgdg110+1))
Type "help" for help.

POC=# CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION
POC=# \q

➏ 対象スキーマへデータを流し込み

DESKTOP-8B:~/win/GIS$ psql -h 127.0.0.1 -p 5432 -U postgres POC < kanko_point_tokyo.sql
Password for user postgres:
SET
SET
BEGIN
CREATE TABLE
ALTER TABLE
                  addgeometrycolumn
-----------------------------------------------------
 public.p12a-14_13.geom SRID:4326 TYPE:POINT DIMS:2
(1 row)

COPY 36
CREATE INDEX
COMMIT
ANALYZE
DESKTOP-8B:~/win/GIS$

❼ 取り込んだデータの確認

PostGIS

MySQLの場合

こちらは、個人的に最も得意なオープンソースデータベースのMySQLにおける取り込み方法になります。 MySQLでは、空間情報を扱う関数などが標準で実装されているので、特に追加のExtention等のインストールは不要ですが、 PostgreSQLと比較すると関数、ツール含めて若干不足気味ではある印象なので、ユーザーのニーズが増えて行ったら、是非拡張して行って頂ければと思います。

❶ MySQLの起動

※ port 33060は Protocol Bufferベースに開発されたX Protocolのポートなので今回は利用していません。

DESKTOP-8B:~/git/rdbms-docker/mysql$ docker-compose -f ./docker-compose-with-volume.yml up -d
Creating network "mysql_default" with the default driver
Creating volume "mysql_mysql-store" with default driver
Creating mysql_db_1 ...
Creating mysql_db_1 ... done
DESKTOP-8B:~/git/rdbms-docker/mysql$



DESKTOP-8B:~/git/rdbms-docker/mysql$ docker-compose ps
   Name                Command             State                           Ports
----------------------------------------------------------------------
mysql_db_1   docker-entrypoint.sh mysqld   Up      0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp
DESKTOP-8B:~/git/rdbms-docker/mysql$

❷ MySQLではデータを取り込む為の専用ツールは提供していないのでGDALを利用します。

DESKTOP-8B:~/git/rdbms-docker/mysql$ sudo apt install gdal-bin
[sudo] password for shinya:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
<SNIP>
DESKTOP-8B:~/git/rdbms-docker/mysql$ ogrinfo --version
GDAL 3.0.4, released 2020/01/28

参考:MySQL 8.0で強化されたGIS機能と使用事例のご紹介+α

❸ ogr2ogrにてデータの変換とデータベースへのデータの取り込み

DESKTOP-8B:~/win/GIS$ ogr2ogr -f "ESRI Shapefile" -lco ENCODING=UTF-8 -oo ENCODING=CP932 P12a-14_13_utf8.shp P12a-14_13.shp
DESKTOP-8B:~/win/GIS$ ogr2ogr -f "MySQL" MySQL:"POC,host=127.0.0.1,user=root,password=password,port=3306" P12a-14_13_utf8.shp

➍ 取り込んだデータの確認

MySQL

データ(sharefile)の取り込みに関しては以上になります。

観光資源データの可視化

  • 時間の都合上MySQLのみでの検証となります。
  • 東京のデータはGPS等で利用されているSRID43264612が設定されていたので無事に取り込めましたが,全国版のShapefileはSRIDが設定されて無い様だったので、Oracle MySQLチームの山﨑氏から紹介して頂いたshp2mysqlを使わせて頂きました。👍

参照:shp2mysql(MySQL8へのインポート用SQLに変換するコマンドラインツール)

github.com

❶ nginx, php, mysqlを構成するコンテナの起動
DESKTOP-8B:~/git/rdbms-docker/mysql$ docker-compose ps
Name   Command   State   Ports
------------------------------
DESKTOP-8B:~/git/rdbms-docker/mysql$ docker-compose -f ./docker-compose-with-volume-web.yml up -d
Creating network "mysql_default" with the default driver
Creating mysql-container ...
Creating mysql-container ... done
Creating php-container ...
Creating php-container ... done
Creating nginx-container ...
Creating nginx-container ... done
❷ shapefileの取り込み
# 1.データダウンロードと解凍

 unzip P12-10_GML.zip

# 2. shp2mysqlのダウンロード(Compile済みなので,展開してそのまま利用出来ます)

 wget https://github.com/hajime-miyauchi/shp2mysql/releases/download/v0.3/shp2mysql-linux.tar.gz

# 3.データの変換

 ./shp2mysql-linux/shp2mysql -s 4612 -W CP932 P12-10-g_TourismResource_Point.shp > P12-10-g_TourismResource_Point_convert.shp

# 4.データの取り込み
 mysql -h 127.0.0.1 -u root -p POC < P12-10-g_TourismResource_Point_convert.shp
❸ インポートしたテーブルとデータの確認
DESKTOP-8B$ mysql -h 127.0.0.1 -u root -p -e "show tables from POC"
Enter password:
+--------------------------------+
| Tables_in_POC                  |
+--------------------------------+
| p12-10-g_tourismresource_point |
+--------------------------------+
国土交通省の観光資源データ:2019件
ST_Geohash(ST_Y(geom),ST_X(geom),2) = 'xn'
➍ 表示範囲の絞り込みとGeoHash

2019件の全データを表示させると、Google Mapの表示に時間がかかったので以下の様にGeoHashを利用して範囲を絞りました。

GeoHashとは?

GeoHashは、エリアを区画に分割して、その区画をBase32でHash化した文字列で表現した値になります。 例えば、以下の例だと東京駅の緯度経度を中心として、計算した5桁のHash値は±2.4kmのエリアを選択します。 この範囲内に存在するデータを生成列で緯度・軽度から自動生成しておいて、インデックスを付与してサクッと同じエリアにあるバス停等を高速に検索する事も可能です。

例)東京駅を中心として±2.4kmにある観光資源
ST_Geohash(ST_Y(geom),ST_X(geom),5) = 'xn76u'
地図表示(xn76u)
参照:Movable Type Scripts

±2.4kmだと少々データ量的には寂しい感じになるので、以下のGeoHashリストから関東エリアをカバー出来そうな2桁のHash値を選択しました。

東京駅から±630kmの観光資源
東京駅を中心としたGeohash

PHP側にはベタで以下のSQLを埋め込んでいます
「年末にでも時間あれば、Vue.jsで検索Boxを作り、観光資源データの拡充を図っていこうかと。。」

$sql = <<<SQL
select p12_003 as 'name',
p12_004 as 'category',
ST_X(geom) AS "lat",ST_Y(geom) AS "lng", 
'kanko' as 'type'  FROM `p12-10-g_tourismresource_point`
where ST_Geohash(ST_Y(geom),ST_X(geom),2) = 'xn'
SQL;
➎ Google Mapでロケーションを可視化
例)霞ケ浦:日本で琵琶湖についで、二番目に大きい面積を持つ湖

これで、基本的な観光資源の可視化が出来たので、データを拡充させてバス停留所データ等を組み合わせたりする事でも便利なコンテンツが出来そうです。

例)観光資源とバス停のデータ集約

参照:ジオハッシュja.wikipedia.org

その他:ジオハッシュを利用したソリューション例dev.classmethod.jp

備考:こちらのコンテナでサクット検証する場合は以下の変更が必要です。

No 概要
1 リポジトリーをCloneしてdocker-compose-with-volume-web.ymlで環境を構築。
2 既にお持ちであれば、Google Map APIキーの変更
3 サンプルとしてユーザー名, パスワード,データベースをそのまま記載しているので必要に応じて.envファイルに変更して下さい。
4 Google Map APIを表示する為に利用するURLを、Google Cloud PlatformにてWeb Site RestrictionsにURLを登録して下さい。

後記

これまでの仕事では観光と関わる事が無かったので、旅行で行く観光地は書店に置いてある雑誌やネットをベースに調べて旅をして来ましたが、 勉強する中で、「高知県には綺麗な川が豊富にある事」、「世界遺産でもある北海道の知床半島が素晴らしいという事」、「本州にも色々な観光名所がある事」に初めて気付く事が出来ました。 家族のタイミングもあるので、なかなかまとまった時間が取れませんが、もしまとまった時間が取れたらこれまで行った事の無い都道府県に旅に行ってみたいと考えてます。 近場?だと富山あたりに行ってトロッコ列車に乗ってみたいと思っています。

この環境を作るにあたり気付いたのですが、PHP7でmysql_connectが非推奨になっている事に初めて気付きました。 もう現場でバリバリという年齢でも無いのでエンジニア業務は殆どしていませんが、どんなに得意な事も日常で触ってないと忘れてしまうので、 週末時間が取れたら、もう少しだけ観光向けのサイトをプライベートで構築して見ようと思います。

年末迄あと少しありますが、健康に気を付けて良い年末・年始をお迎えください。

採用情報

LCLではエンジニアのアイデアを生かして、更にサービスを盛り上げて行こうと思ってます!! 引き続き、生産性向上に励む仲間を募集中です。

「現時点では、特にフロントエンドエンジニアを絶賛募集中です。」 カジュアル面談、少し話を聞いてみたい等、少しでも思われたらご連絡下さい。

www.lclco.com