10
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

群馬県公共交通オープンデータ(GTFS)を一括してデータベースに格納する方法

Last updated at Posted at 2018-12-27

2018年12月26日に、群馬県から県内(ほぼ?)全ての路線バスと一部の私鉄の時刻表データがオープンデータとして公開されました。群馬県のバス会社は、まさに群雄割拠というか中小コミュニティバスが入り乱れている状況ですが、データという点では、「標準的なバス情報フォーマット(GTFS-JP)」という形式で揃ったことになります。ちなみにこの形式は、世界的なデファクトスタンダードであるGTFS形式と互換性があり、Google MapsやYahoo!路線情報などで幅広く使われています。

群馬県交通まちづくり戦略によると、群馬県は「公共交通の分担率はわずか2.8 %(鉄道2.5%、バス0.3%)と低く、年間を通して一度も鉄道・バスを利用しない県民は約60%」という極端な車社会です。そのため、オープンデータを活用してバスの利便性を高め、県民の足としてバスの認知を高めてゆくことが望まれています。

そこで、この記事では先日書いた「GTFSファイルをマージしてPostgreSQL+PostGISに投入する方法」を参考に、群馬県のデータを一括してダウンロード、DBに格納する方法を説明します。

データの活用方法に関しては、「PostgreSQL+PostGISに格納したGTFS形式の公共交通オープンデータを操作する」という記事を同時に書いているので、参考にしてください。

チート

本来は以下に説明する手順を踏まえて作業する必要がありますが、アプリ開発を容易にするため、ここで作成したデータを共有します(2018年12月26日公開時点で作成2018年12月28日時点に更新)。本データは無保証であり、また以下の作業の性質上各IDが書き換わっています。利用される場合は、元データのライセンスに従って利用してください。

pg_dump -Fc gtfs-gunma > gtfs-gunma.dump で作成したダンプファイルです。PostgreSQL+PostGISがインストールされてる環境で、 pg_restore -C -d postgres gtfs-gunma.dump とすることでデータベースを作成出来ます。

pgAdmin4を用いてデータベースを作成する場合、(1)Databasesを右クリック→Create→Database で gtfs-gunma という名称のDBを作成、(2)作成したgtfs-gunmaを右クリック→Restore→Filenameを指定してRestoreを実行します。

詳細な作業手順

##データの一括ダウンロード
公開されたデータは「群馬県内バス路線情報(標準的なバス情報フォーマット)」というページからダウンロードが出来ますが、事業者ごとに分割された40個ものGTFSファイルなので、まずはこれを一括してダウンロードする必要があります。このページではダウンロードがJavaScriptで処理されており、ファイルのURLが不明ですが、htmlファイルの中身をよく見ると、https://gma.jcld.jp/GMA_OPENDATA/opendata.json というURLでこのページを構成するJSONデータにアクセスできることが分かります。以下にデータの一部分を抜粋します。ここに入っているzip_pathがGTFSファイルのURLのようですね。

opendata.json(一部分)
[
  {
    "title": "上信電鉄",
    "zip_file": [
      {
        "zip_title": "上信電鉄",
        "zip_path": "//gma.jcld.jp/GMA_OPENDATA/GTFS/gtfs.1013.joshin_bus.zip",
        "date": "20180530",
        "lines": [
          "高崎駅~前橋駅・中央前橋駅",
          "高崎問屋町駅~鶴辺団地"
        ],
        "file_date": "20181220"
      }
    ]
  },
  {
    "title": "関越交通",
    "zip_file": [
      {
        "zip_title": "関越交通",
        "zip_path": "//gma.jcld.jp/GMA_OPENDATA/GTFS/gtfs.1001.kanetsu_kotu.zip",
        "date": "20181201",
        "lines": [],
        "file_date": "20181225"
      }
    ]
  },
  {
    "title": "群馬バス",
    "zip_file": [
      {
        "zip_title": "群馬バス",
        "zip_path": "//gma.jcld.jp/GMA_OPENDATA/GTFS/gtfs.1007.gunma_bus.zip",
        "date": "20181127",
        "lines": [],
        "file_date": "20181220"
      }
    ]
  }
]

次に、このこのURLのファイルを一括ダウンロードするプログラムを作ります。JSONの処理を考え、Rubyで作ってみました。

01-download-gunma.rb
#! /usr/bin/ruby

require 'open-uri'
require 'json'

url='https://gma.jcld.jp/GMA_OPENDATA/opendata.json'
download_path = 'gtfs' # ダウンロードしたファイルを保存するディレクトリ

file= open(url)
json = JSON.load(file)
json.each do |element|
  data = element['zip_file']
  name = data[0]['zip_title'] #1つの事業者に2個以上のファイルを格納した例がないため0で決め打ち
  gtfs_url = 'http:' + data[0]['zip_path']
  base_name = File.basename(gtfs_url)
  write_file = download_path + '/' + base_name
  
  puts name
  puts gtfs_url

  open(gtfs_url) do |file|
    open(write_file, "w+b") do |out|
      out.write(file.read)
    end
    File::utime(file.last_modified, file.last_modified, write_file)
  end
end

# 最後にjsonファイルを保存する
file.rewind
open(File.basename(url), "w+b") do |out|
  out.write(file.read)
end

適当にディレクトリを作成し、このスクリプトを実行してまずはファイルをダウンロードします。以下ではUNIX環境の例を書きましたが、コマンドなどはそれぞれの環境に合わせて読み替えてください。

$ mkdir gunma               # 適当にディレクトリを作成
$ cd gunma
$ vi 01-download-gunma.rb   # 上記スクリプトを作成
$ mkidr gtfs                # ダウンロードするディレクトリを作成
$ ruby 01-download-gunma.rb # スクリプトの実行

GTFSデータの解凍

GTFSファイルをマージするために、一括で解凍します。UNIX環境ならば、シェルスクリプトで実行しましょう。このコマンドで、uncompressedというディレクトリ内にサブディレクトリが作られ、その中にGTFSファイルがそれぞれ展開されます。

02-uncompress.sh
#!/bin/bash

GTFSDIR='gtfs'
EXTRACTDIR='uncompressed'

rm -rf $EXTRACTDIR
mkdir $EXTRACTDIR

for FILE in $GTFSDIR/*.zip
do
    FILENAME=`basename $FILE`
    DIRNAME=${FILENAME%.*}
    echo '==============='
    echo $FILENAME
    mkdir $EXTRACTDIR/$DIRNAME
    unzip $FILE -d $EXTRACTDIR/$DIRNAME
done

仕様に沿わないデータの修正(2018年12月27日更新でこの作業は不要になりました)

このままデータのマージ作業を始めたいところですが、一部のデータに仕様に従っていないところがあり、このまま進めるとエラーとなるため、手作業で修正します。具体的には、 gtfs.0002.express.GMA/agency.txt(高速バス)、gtfs.0003.lim.GMA/agency.txt(空港リムジンバス) それぞれの、agency_urlが空欄となっています(仕様では必須)。適当なエディタで、ここに適当なURLを記入します。

GTFSデータのマージ

GTFSファイルをマージしてPostgreSQL+PostGISに投入する方法で利用したonebusaway-gtfs-merge-cliをここでも利用します。ビルド手法などは以前の記事を参照してください。この手法だと、マージの際にIDが書き換わってしまうのが問題なのですが、とりあえず目をつぶります。今回もファイル数が多いのでシェルスクリプトで実行します。

03-merge.sh
#!/bin/bash

MERGEDDIR='merged'
JARFILE='onebusaway-gtfs-merge-cli-1.3.48.jar'

rm -rf $MERGEDDIR
mkdir  $MERGEDDIR

unset FILES; 
for DIR in uncompressed/*;
do
    FILES=$FILES\ $DIR;
done
echo $FILES;

java -jar $JARFILE $FILES $MERGEDDIR

cd $MERGEDDIR
zip GTFS.zip *.txt

なおこの処理はとても時間がかかります。私の環境(MacBook Pro 15inch 2016年モデル)では2時間16分かかりました。

データベースへの投入

出力されたmerged/GTFS.zipをPostgreSQL+PostGISに投入します。詳細はGTFSファイルをマージしてPostgreSQL+PostGISに投入する方法#GTFSファイルのデータベースへの投入をご覧ください。ここでは、これまでの流れと同じくスクリプトにして実行します。

04-import-db.sh
#!/bin/bash

DBNAME='gtfs-gunma'
GTFSFILE='merged/GTFS.zip'

dropdb --if-exists $DBNAME
createdb $DBNAME
psql -d $DBNAME -c "create extension postgis"
../gtfsdb/bin/gtfsdb-load --database_url postgresql://localhost:5432/$DBNAME --is_geospatial $GTFSFILE

これでデータベースへの投入が完了しました。

10
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?