LoginSignup
12
16

More than 3 years have passed since last update.

シェープファイルをGeoJSON形式に変換する

Posted at

前提

zip圧縮されたシェープファイル群(.shp, .shx, .dbf)を、GeoJson形式で出力する関数です。
当然、シェープファイル群のファイル名が共通している必要があります。
また、.geojsonファイルを出力するのではなく、メモリ上で処理します。
事前にpyshp(shapefile)が必要になります。

コード

import shapefile, io, zipfile

#zipファイルからshpファイルを探してファイル名を取得
def find_shpfile_inzip(zipped_shp):
    zip_infolist = zipped_shp.infolist()
    for info in zip_infolist:
        if not info.filename.startswith('__MACOSX/'): #Mac-ZIP対応
            if info.filename.endswith('.shp'):
                return info.filename

まずこのように、zip圧縮されたshapefileのファイル名を取得する関数を定義します。
この関数を用いて

#ZIP保存されたSHP群をGEOJSON形式で返す
def zipped_shp_to_geojson(zipped_shp):
    zipped_files = zipfile.ZipFile(zipped_shp)

    #zipファイルからshpファイルを探してファイル名を取得
    shp_name = find_shpfile_inzip(zipped_files)[:-4]

    #shapefile読み込みと適合判定
    try:
        shp_file_bytes = zipped_files.read(shp_name + '.shp')
        shx_file_bytes = zipped_files.read(shp_name + '.shx')
        dbf_file_bytes = zipped_files.read(shp_name + '.dbf')
    except:
        print("Imported file was not apropriate Shape-Zip-File.")
        return None

    geojson = dict(type="FeatureCollection", features=[])
    #pyshpはライブラリ内部でデコードするので、正しいエンコーディングでデコード出来るまでループ
    for codec in CODECS:
        try:
            reader = shapefile.Reader(shp=io.BytesIO(shp_file_bytes),
                                        shx=io.BytesIO(shx_file_bytes),
                                        dbf=io.BytesIO(dbf_file_bytes),encoding=codec)

            fields = reader.fields[1:]
            field_names = [field[0] for field in fields]
            for sr in reader.shapeRecords():
                atr = dict(zip(field_names, sr.record))
                geom = sr.shape.__geo_interface__
                geojson['features'].append(dict(type="Feature", \
                 geometry=geom, properties=atr))
            print(codec + 'encoding is correct.' )
            break
        except UnicodeDecodeError:
            print(codec + 'is not suitable for this file.')
            continue
    return geojson

これでgeojsonに変換されます。
エンコーディングについてはコメントのとおりです。pyshpではデフォルトだとUTF-8でデコードされますが、オープンデータで提供されるシェープファイルは、大半がcp932(Windows環境のShift-JIS)です。エンコーディングの指定が間違っているとUnicode errorが発生します。それならcp932を指定してデコードすれば良いのでは、と考えますが、当然ながらUTF-8等にも対応しておきたいところです。したがって、メジャーなエンコーディングのなかから適合するまでデコードし続けるようになっています(このモジュールの冒頭で、CODECS定数を定義してある)。

12
16
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
12
16