国土地理院基盤地図情報のGMLファイルをGNU Parallelを使用して並行処理するシェルスクリプト

作成日
キーワード
並行処理 基盤地図情報 GML parallel

国土地理院の基盤地図情報サイトで公開されている基本項目や数値標高モデルのGMLファイルをGNU Parallelを使用して並行処理するシェルスクリプトを紹介します。

基盤地図情報の基本項目のGMLをパースすると、道路縁、建築物の外周線、軌道の中心線等の情報をポリゴンや線として取得することができます。

これらのデータを使用して、例えば地図を描画や各種の可視化、機械学習のための前処理データ作成などを行うことができます。

いっぽう、データは多数のメッシュに分けて公開されているため、少し大きな領域、例えば東京都を覆う領域のデータを扱いたい場合は、合計で64個ほどのファイルを処理することになります。

例えば、東京都を覆うサイズのメッシュの基本項目のGMLファイルは、次のような64ファイルほどになりました。

FG-GML-533900-ALL-20200401.zip
FG-GML-533901-ALL-20210101.zip
FG-GML-533902-ALL-20200401.zip
FG-GML-533903-ALL-20201001.zip
FG-GML-533904-ALL-20210101.zip
FG-GML-533905-ALL-20201001.zip
FG-GML-533906-ALL-20201001.zip
FG-GML-533907-ALL-20210101.zip
# 中略
FG-GML-533977-ALL-20201001.zip

また、配布されているGMLはzipで圧縮されており、その中に「海岸線」、「道路縁」、「軌道の中心線」、「水涯線」、「建築物の外周線」等の項目が各レイヤーに別れたGMLとして納められた構造になっています。

例えば、FG-GML-533962-ALL-20210101.zipのようなzipファイルについてみてみます。

次のように、建築物、建築物の外周線、道路縁や道路構成線のようなレイヤーに分けられたGMLが入っていることがわかります。

$ unzip -l FG-GML-533962-ALL-20210101.zip
Archive:  FG-GML-533962-ALL-20210101.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
   119964  12-07-2020 19:21   FG-GML-533962-AdmArea-20210101-0001.xml
   669525  12-07-2020 19:21   FG-GML-533962-AdmBdry-20210101-0001.xml
     4454  12-07-2020 19:21   FG-GML-533962-AdmPt-20210101-0001.xml
 75906887  12-07-2020 19:21   FG-GML-533962-BldA-20210101-0001.xml
 59727811  12-07-2020 19:21   FG-GML-533962-BldL-20210101-0001.xml
 13543050  12-07-2020 19:21   FG-GML-533962-Cntr-20210101-0001.xml
  1599365  12-07-2020 19:21   FG-GML-533962-CommBdry-20210101-0001.xml
    52556  12-07-2020 19:21   FG-GML-533962-CommPt-20210101-0001.xml
    85891  12-07-2020 19:21   FG-GML-533962-ElevPt-20210101-0001.xml
    26005  12-07-2020 19:21   FG-GML-533962-GCP-20210101-0001.xml
   476156  12-07-2020 19:21   FG-GML-533962-RailCL-20210101-0001.xml
  3332794  12-07-2020 19:21   FG-GML-533962-RdCompt-20210101-0001.xml
 18494372  12-07-2020 19:21   FG-GML-533962-RdEdg-20210101-0001.xml
   117906  12-07-2020 19:21   FG-GML-533962-SBAPt-20210101-0001.xml
   837283  12-07-2020 19:21   FG-GML-533962-SBBdry-20210101-0001.xml
  2348559  12-07-2020 19:21   FG-GML-533962-WA-20210101-0001.xml
  4720822  12-07-2020 19:21   FG-GML-533962-WL-20210101-0001.xml
   113577  12-07-2020 19:21   FG-GML-533962-WStrA-20210101-0001.xml
   210531  12-07-2020 19:21   FG-GML-533962-WStrL-20210101-0001.xml
     4873  11-30-2020 10:26   fmdid21-0101.xml
---------                     -------
182392381                     20 files

このため、「東京都全域の建物のポリゴンを取得して一定の処理を行った後DBに登録する」ような処理をしたい場合は、64個のGMLファイルの中の、ファイル名にBldAを含むXMLファイルをパースして処理し、DBに登録する処理を実行することになります。

すると、各処理について相応の時間がかかることが想定されるため、「ファイルをパースして処理し、DBに登録する処理を実行」を並行して処理したくなります。

そこでシェルスクリプト

ここでは、GNU Parallelをbashのシェルスクリプトの中で使用して10並行の並行処理を行うようにしました。

次のようなスクリプトになりました。

#!/usr/bin/env bash

path_and_filenames=()

for i in `ls $PWD/*zip`; do
  gml_filenames=`unzip -l $i | grep "BldA" | awk '{print $4}'`

  for j in $gml_filenames; do
    path_and_filenames+=("${i},${j}")
  done
done

function process() {
  o=$1
  list=(${o//,/ })

  path=${list[0]}
  filename=${list[1]}

  # ここで、各ファイルのGMLからpostgisに登録する処理 ogr2ogr使用
  # まず解凍
  unzip -o -j $path $filename -d $PWD
  
  # 解凍したファイルを使用してベットの処理を行ったのちにDBに登録
  # CやRustで書いた別のコマンドに当該ファイルを引数で与えて実行します(割愛)

  # 完了したら、解凍済みのファイルを削除
  rm $PWD/$filename
}

export -f process

parallel --progress -j 10 "process {}" ::: ${path_and_filenames[@]}

MacBook Pro(2016年前後の古いもの。Intel Core i5 3.1 GHz、メモリ 16 GB)を使用した場合、東京全体のBldAレイヤーの約770万行のインポートが2時間で完了しました。