日本全国避難所データと現在地周辺の避難所地図を公開しました

[OpenData] : 日本全国避難所データと現在地周辺の避難所地図を公開しました

避難所

防災情報 全国避難所ガイド | ホーム はてなブックマーク - 防災情報 全国避難所ガイド | ホーム
避難所マップ - Yahoo!天気・災害 はてなブックマーク - 避難所マップ - Yahoo!天気・災害

@yutakikucです。オープンデータへの貢献という大義名分っぽい事を掲げ、避難所データを構造化テキストで作成し、更にはポイントを地図上へのマッピングします。避難所というと1st MediaのアプリやYahoo!避難所マップに情報が掲載されていますが、それ以外の避難所野良Web等は避難所データが整理されていません。Yahoo!避難所マップも都道府県毎に公開/非公開があるようでこちらもデータとしては不十分です。今回僕がデータ作成と簡単な地図マッピングを行うので、これを参考に良いアプリケーションが出てくる事に期待しています。

作成した避難所データと地図

作成した避難所データはgithub、それをマッピングした地図をGAEで公開します。地図はGeoLocationAPIを利用して現在地付近の避難所のみを取得します。※利用は全て自己責任でお願いいたします。

公開地図

避難所マップ はてなブックマーク - 避難所マップ

避難所データソース

都道府県避難施設一覧 - 内閣官房 国民保護ポータルサイト はてなブックマーク - 都道府県避難施設一覧 - 内閣官房 国民保護ポータルサイト
1st Mediaの避難所データ はてなブックマーク -
内閣官房 国民保護ポータルサイトのデータを利用します。注意として「平成22年4月1日現在のデータを参考として掲載しております。」とあるようにデータが最新の物では無いです。上のサイトに掲載されているpdfからtextを抽出し、構造化テキストに変換します。代替のデータソースとしては1st MediaのWebPageに掲載されているデータを引っ張ってくる方法もいいかと思いますが、取り扱いには注意してください。

避難所構造化テキスト作成

pdftotextを利用した避難所YAMLファイルの生成

まずはpdfからtextに変換する為のツールであるpdftotextをCentOS6.4へinstallします。install後に国民保護ポータルサイトからpdfファイルをdownloadして、pdftotextコマンドを実行してみます。pdftotextにより標準出力されたデータを見てみるとちゃんと変換されていることが分かりますが、pdf中の表に入力された改行がそのまま改行として出力されています。改行が1つであれルール化できそうですが、2つ以上ある箇所は改行がメイン行の前後に出力されるので、そのようなデータを拾う事はここでは諦めました。拾いたい場合は人の目で判断する必要があると思います。
pythonにはpdfをtext変換するpyPdf はてなブックマーク - pyPdfライブラリもあるので、そちらを使っても良いと思います。

$ sudo yum install  poppler-utils -y
$ wget http://www.kokuminhogo.go.jp/pdf/hinan_hokkaido.pdf
$ pdftotext -enc UTF-8 -layout -nopgbrk hinan_hokkaido.pdf - 
 46    円山公園                     札幌市     円山西町8丁目 
                                    宮の森1214丁目他
 47    旭山記念公園                   札幌市     中央区界川4丁目
                                    中央区中島公園
 48    中島公園                     札幌市     南14条西5丁目
                                    南15条西4丁目

YOLP(地図):Yahoo!ジオコーダAPI - Yahoo!デベロッパーネットワーク はてなブックマーク - YOLP(地図):Yahoo!ジオコーダAPI - Yahoo!デベロッパーネットワーク
Google Geocoding API - Google Maps API ウェブ サービス ― Google Developers はてなブックマーク - Google Geocoding API - Google Maps API ウェブ サービス ― Google Developers

次に以下のPythonコードを実行して、各都道府県の避難所データをYAMLに変換します。生成するYAMLデータ形式都道府県 - 市区町村 - 番地名 - ( 緯度経度 / 場所名[配列] )の4階層になっています。 緯度経度のデータを取得にはYahoo!のジオコーダーAPIを利用しました。Googleのジオコーダーを利用したかったのですが、APIへのリクエスト数上限に引っかかり、OVER_QUERY_LIMITというエラーが頻発するのでYahoo!を使いました。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 避難所データの構造化テキスト作成
# shelter.pyとして保存する
import os,sys,time,re,urllib,urllib2,yaml,json,unicodedata,time
url = 'http://www.kokuminhogo.go.jp/hinan/index.html'
opener = urllib2.build_opener()
ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.51.22 (KHTML, like Gecko) Version/5.1.1 Safari/    534.51.22'
referer = 'http://www.kokuminhogo.go.jp/'
opener.addheaders = [('User-Agent', ua),('Referer', referer)]
appid = 'Yahoo!' # yahooapiのappidをここに定義
try:
   html = unicode(opener.open(url).read(), 'cp932') 
   if re.compile(r'(.*?), re.M).search(html) is not None:
  data = re.compile(r'(.*?), re.M).findall(html) 
  # pdf download
  for line in data:
     dict = {}
     os.system('wget http://www.kokuminhogo.go.jp' + line[0].replace('..', ''))
     # pdftotext
     textfile = line[0].replace('../pdf/', '').replace('.pdf', '.txt')
     os.system("pdftotext -enc UTF-8 -layout -nopgbrk %s - | sed '/^$/d' | sed 's/^ \+//g' | sed 's/ \{2,\}/\t/g' | sed 's/ //g' | grep '^[0-9]\+'$'\t' | cut -f 2,3,4 | awk '{ print $2%s$3%s$1}' > %s" % (line[0].replace('../pdf/', ''), '"\t"', '"\t"', textfile))
     f = open(textfile, 'r')
     for node in f.readlines():
        (mun,adr,name) = node.rstrip().split("\t")
        if mun == '' or adr == '' or name == '' or name == '/':
           continue
        mun = unicodedata.normalize('NFKC', unicode(mun, 'utf-8'))
        adr = unicodedata.normalize('NFKC', unicode(adr, 'utf-8'))
        name = unicodedata.normalize('NFKC', unicode(name, 'utf-8'))
        dict.setdefault(line[1], {}).setdefault(mun, {}).setdefault(adr, {}).setdefault('name', [] )
        # geoencoding
        #url = "http://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false" %(urllib.quote_plus(mun.encode('utf-8') + adr.encode('utf-8')))
        latlng = ''
        try:
           time.sleep(0.2)
           url = 'http://geo.search.olp.yahooapis.jp/OpenLocalPlatform/V1/geoCoder?appid=%s&query=%s&output=%s' % (appid, urllib.quote_plus(mun.encode('utf-8') + adr.encode('utf-8')), 'json')
           res = json.loads(opener.open(url).read())
           if (res['ResultInfo']['Status'] == 200 and res['ResultInfo']['Count'] > 0 ):
              (lng,lat) = res['Feature'][0]['Geometry']['Coordinates'].split(',')
              latlng = lat + ',' + lng
           dict[line[1]][mun][adr]['latlng'] = latlng
           dict[line[1]][mun][adr]['name'].append(name)
        except urllib2.URLError:
           dict[line[1]][mun][adr]['latlng'] = latlng
           dict[line[1]][mun][adr]['name'].append(name)
           continue
     f.close()
     # yaml generator
     savefile = open(textfile.replace('.txt', '').replace('hinan_', '') + '_shelter.yaml', 'w')
     yaml.safe_dump(dict, savefile, default_flow_style=False, encoding='utf8', allow_unicode=True)
except Exception, e:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno) 
# 都道府県名:
  # 市区町村名:
 # 番地名:
    # latlng:
    # name:
    # - 場所名
    # - 場所名

東京:
  あきる野市:
上代継190:
  latlng: 35.72992747,139.27797845
  name:
  - あきる野市立西中学校校庭
  - あきる野市立西中学校体育館

その他のオープンデータ

以下は過去に様々なサイトからデータを抽出した個人のオープンデータになります。
こちらも利用される場合は全て自己責任でお願いいたします。
業種別企業の平均年齢と年収の辞書データを公開しました - Yuta.Kikuchiの日記 はてなブックマーク - 業種別企業の平均年齢と年収の辞書データを公開しました - Yuta.Kikuchiの日記
業種別企業名辞書データを公開しました - Yuta.Kikuchiの日記 はてなブックマーク - 業種別企業名辞書データを公開しました - Yuta.Kikuchiの日記
地域データの構造化テキストを公開しました。 - Yuta.Kikuchiの日記 はてなブックマーク - 地域データの構造化テキストを公開しました。 - Yuta.Kikuchiの日記