GTFSファイルをマージしてPostgreSQL+PostGISに投入する方法

## はじめに
公共交通オープンデータが広まるにつれて、ダイヤデータなどをGTFS形式（標準的なバス情報フォーマット）で公開する交通事業者も増えてきました。ここでは、複数のGTFSファイルをまとめてデータベースに投入する方法を解説します。1つの地域に複数の交通事業者がある場合などに、複数のGTFSをまとめるのは有効ですし、データベースへの投入手法も専用ツールを用いることで簡単に行うことが出来ます。

## 環境

この記事は以下の環境で動作確認しています。各ソフトウェアのインストール方法などは解説しませんが、私の手元では、 Homebrew 1.7.6 にて環境構築を行っています。

- OS: macOS High Sierra 10.13.6
- PostgreSQL 10.5 
- PostGIS 2.5
- Python 2.7.15
- [zc.buildout](https://pypi.org/project/zc.buildout/) 2.12.2
- Java 8 (1.8.0_112)
- Apache Maven 3.5.4 

## 利用するデータ

ここでは、「[公共交通オープンデータ最先端都市 岡山](http://d-cradle.or.jp/forum2018/)」の5事業者のデータを利用します。リンク先から静的データ（GTFS・標準的なバス情報フォーマット）を入手してください。

| 事業者                | 静的データ公開       |動的データ公開| 更新頻度 |ラインセンス| 入手先 |
|:---------------------|:-------------------:|:------------------:|---:|:--|:--|
| 宇野バス              | ○                   | ○(TripUpdate, VehiclePosition)             |20秒|CC-BY 4.0|[宇野バス　オープンデータ](http://www3.unobus.co.jp/opendata/)|
| 下電バス              | ○                   |×|-|CC-BY 4.0|[下津井電鉄オープンデータ](http://www.shimoden.net/busmada/opendata/)|
| 両備バス（両備グループ）| ○                   | ○(TripUpdate, VehiclePosition)|15秒|CC-BY 4.0|[BusVisionデータダウンロード](https://loc.bus-vision.jp/ryobi/view/opendata.html)|
| 岡電バス（両備グループ）| ○                   | ○(TripUpdate, VehiclePosition)|15秒|CC-BY 4.0|[BusVisionデータダウンロード](https://loc.bus-vision.jp/ryobi/view/opendata.html)|
| 中鉄バス              | ○（β版・一部路線のみ）|×|-|CC-BY 4.0|[BusVisionデータダウンロード](https://loc.bus-vision.jp/ryobi/view/opendata.html)|
| 八晃運輸 （めぐりん）  | ×                   |×|-||[2018年5月時点の非公式データがあり](http://koutsu.tech/okayama-gtfs-180529/)|


## GTFSのマージ

### onebusaway-gtfs-merge-cliのダウンロード
GTFSファイルのマージには、[onebusaway-gtfs-merge-cli](http://developer.onebusaway.org/modules/onebusaway-gtfs-modules/1.3.3/onebusaway-gtfs-merge-cli.html)というツールを利用します。リンク先からjarファイルをダウンロード出来ますが、バージョンが古くうまく動かないため、最新バージョンを手元の環境でビルドします。[GitHubのonebusaway-gtfs-modules](https://github.com/OneBusAway/onebusaway-gtfs-modules/releases)から、最新のリリースをダウンロードします。記事執筆時点でバージョン1.3.48が最新でした。

### onebusaway-gtfs-merge-cliのビルド

Mavenを利用してonebusaway-gtfs-modulesをビルドします。必要なライブラリなどをダウンロードするため時間がかかりますが、ビルドが完了するとjarファイルが出力されます。

```Console:onebusaway-gtfs-modulesのビルド
$ tar xzvf onebusaway-gtfs-modules-1.3.48.tar.gz
$ cd onebusaway-gtfs-modules-onebusaway-gtfs-modules-1.3.48/
$ mvn install
```

ビルドが成功すると、 `onebusaway-gtfs-modules-onebusaway-gtfs-modules-1.3.48/onebusaway-gtfs-merge-cli/target/` 以下に `onebusaway-gtfs-merge-cli-1.3.48.jar`というファイルが出力されます。

### 作業環境の構築

マージ作業用のディレクトリを作成し、その下に各社のディレクトリを作成してGTFSファイルの内容を解凍しましょう。ここでは、`uno`、`shimoden`、`ryobi`、`okaden`、`chutetsu`というディレクトリを用意しました。また、出力用に`merged`というディレクトリも作成します。ビルドしたjarファイルも作業用ディレクトリにコピーします。この時点で以下のようなディレクトリ構成になります。

```Console:mergeの作業環境
merge/
├── chutetsu
│   ├── agency.txt
│   ├── （略）
│   └── trips.txt
├── merged
├── okaden
│   ├── agency.txt
│   ├── （略）
│   └── trips.txt
├── onebusaway-gtfs-merge-cli-1.3.48.jar
├── ryobi
│   ├── agency.txt
│   ├── （略）
│   └── trips.txt
├── shimoden
│   ├── agency.txt
│   ├── （略）
│   └── trips.txt
└── uno
    ├── agency.txt
    ├── （略）
    └── trips.txt
```

### マージの実行

作業ディレクトリで以下のコマンドを打つことで、マージが実行されます。完了すると、merged ディレクトリ以下にファイルが出力されます。最後に、ZIP圧縮してGTFSファイルを作成します。

```Console:GTFSマージの実行
$ java -jar onebusaway-gtfs-merge-cli-1.3.48.jar uno/ shimoden/ ryobi/ okaden/ chutetsu/ merged/
$ cd merged/
$ zip GTFS.zip *.txt 
  adding: agency.txt (deflated 41%)
  adding: calendar.txt (deflated 77%)
  adding: calendar_dates.txt (deflated 83%)
  adding: fare_attributes.txt (deflated 90%)
  adding: fare_rules.txt (deflated 92%)
  adding: routes.txt (deflated 89%)
  adding: shapes.txt (deflated 76%)
  adding: stop_times.txt (deflated 90%)
  adding: stops.txt (deflated 66%)
  adding: trips.txt (deflated 92%)
```

## GTFSファイルのデータベースへの投入

地理空間演算機能を備えたリレーショナルデータベースであるPostgreSQL+PostGISにマージされたGTFSファイルを投入します。

### GTFSDBのダウンロードとビルド

データベースへの投入には、[GTFSDB](https://github.com/OpenTransitTools/gtfsdb)というツールを用います。これをドキュメントに従ってインストールします。


```Console:GTFSDBのビルド
$ git clone https://github.com/OpenTransitTools/gtfsdb.git
$ cd gtfsdb 
$ buildout install prod postgresql
```

### データベースの初期化

```Console:PostgreSQL、PostGISを用いたDB初期化
$ createdb gtfs-test
$ psql -d gtfs-test
gtfs-test=# create extension postgis;
CREATE EXTENSION
gtfs-test=# \q
```

### 投入の実行

```Console:GTFSDBを用いたGTFSファイルのデータベースへの投入
$ bin/gtfsdb-load --database_url postgresql://[user]@localhost:5432/gtfs-test --is_geospatial GTFS.zip 
```

ちなみに、PostgreSQLのURLは、[こちらのドキュメント](https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING)によると一般的に以下のように表現されます。自身の環境に合わせてください。
> postgresql://[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&...]

## おわりに
ここまでの作業でGTFSのマージとデータベースへの投入が完了しました。構築したデータベースを利用して遊んでみてください。最後に、動作確認を兼ねて、pgAdmin 4で地図上にバス停（stops）一覧を表示した図を示します。

![スクリーンショット 2018-10-10 22.56.41.png](https://qiita-image-store.s3.amazonaws.com/0/53416/a399f8f8-4332-cd00-1c1e-69ae0b6eacd9.png)