Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

地域データの構造化テキストを公開しました。

[asin:B003VWCBXI:detail]

はじめに

読み仮名データの促音・拗音を小書きで表記するもの - zip圧縮形式 日本郵便 はてなブックマーク - 読み仮名データの促音・拗音を小書きで表記するもの - zip圧縮形式 日本郵便
駅データ 無料ダウンロード 『駅データ.jp』 はてなブックマーク - 駅データ 無料ダウンロード 『駅データ.jp』


最近は専らデータの整形屋になっている@yutakikucです。今日は日本郵便株式会社と駅データ.jpに掲載されているデータを利用して、地域データを構造化テキストとして作成します。ここでの目的は上のリンクで公開されている地域データの形式がCSVだったり、WebAPIのXMLだったり、データが1箇所にまとめられていなかったりと少し不便を感じたので構造化テキストを作成することにしました。出力形式は名前ベースのYAMLです。尚、下で公開したデータの利用は全て自己責任でお願い致します。

PyYAMLの利用

YAML形式をGenerateする言語はpythonを利用します。pythonYAMLライブラリのPyYAMLを使うのでその設定方法を書いておきます。import yamlが実行出来れば設定が完了しています。

$ wget "http://pyyaml.org/download/pyyaml/PyYAML-3.10.zip"

$ unzip PyYAML-3.10.zip

$ cd PyYAML-3.10

$ sudo python setup.py install

$ python
Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) 
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import yaml
>>>

地域名データ/郵便番号のYAML

県名、市区町村のデータの冗長化を防ぐためにYAMLのkeyとして設定しデータに重複が発生しないようにしています。以下が簡単なDataFormatとSampleDataです。日本郵便のサイトからDataをDownloadしてYAMLファイルを生成するのを下のPythonで自動的にやってくれますが、僕が試しに実行してみたところ処理に5分程掛かってしまい少し重たく感じます。生成したファイルをGithubに上げました。

Github
$ git clone git@github.com:yutakikuchi/Data.git
DataFormat/SampleData
県名:
  市名:
     町村名:
       city_kana:市名のカナ表記
       prefecture_kana:県名のカナ表記
       town_kana:町村名のカナ表記
       zipcode:郵便番号
新潟県:
  三島郡出雲崎町:
    上中条:
      city_kana: サントウグンイズモザキマチ
      prefecture_kana: ニイガタケン
      town_kana: カミナカジョウ
      zipcode: '9494341'
    上野山:
      city_kana: サントウグンイズモザキマチ
      prefecture_kana: ニイガタケン
      town_kana: ウエノヤマ
      zipcode: '9494346'
    中山:  
      city_kana: サントウグンイズモザキマチ
      prefecture_kana: ニイガタケン
      town_kana: ナカヤマ
      zipcode: '9494345'
    久田:  
      city_kana: サントウグンイズモザキマチ
      prefecture_kana: ニイガタケン
      town_kana: クッタ
      zipcode: '9494301'
generate YAML
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 地域情報のYAML化 

import sys,re,urllib,zipfile,os,yaml
zip_url = 'http://www.post.japanpost.jp/zipcode/dl/kogaki/zip/ken_all.zip';
urllib.urlretrieve( zip_url,  './ken_all.zip' )
zf = zipfile.ZipFile( './ken_all.zip', 'r' )
dict_data = {}
non_string = u'以下に掲載がない場合'
for f in zf.namelist():
   if not os.path.basename(f):
      break
   else:
      try:
         data = open( f, 'r' )
         for line in data:
            try:
               line =  line.decode( 'cp932' ).replace( '"', '' )
               nodes = line.split(',')
               zipcode = nodes[2] if nodes[2] is not None and nodes[2] != '' and nodes[2] != non_string else 'N/A'
               prefecture_kana = nodes[3] if nodes[3] is not None and nodes[3] != '' and nodes[3] != non_string else 'N/A'
               city_kana = nodes[4] if nodes[4] is not None and nodes[4] != '' and nodes[4] != non_string else 'N/A'
               town_kana = nodes[5] if nodes[5] is not None and nodes[5] != '' and nodes[5] != non_string else 'N/A'
               prefecture = nodes[6] if nodes[6] is not None and nodes[6] != '' and nodes[6] != non_string else 'N/A'
               city = nodes[7] if nodes[7] is not None and nodes[7] != '' and nodes[7] != non_string else 'N/A'
               town = nodes[8] if nodes[8] is not None and nodes[8] != '' and nodes[8] != non_string else 'N/A'
               dict_data.setdefault( prefecture, {} ).setdefault( city, {} ).setdefault( town, {} )
               dict_data[prefecture][city][town]['zipcode']  = zipcode.encode( 'utf-8' )  
               dict_data[prefecture][city][town]['prefecture_kana'] = prefecture_kana
               dict_data[prefecture][city][town]['city_kana'] = city_kana
               dict_data[prefecture][city][town]['town_kana'] = town_kana
            except UnicodeEncodeError:
               continue
      except Exception, e:
         print str(e) 
         continue
savefile = open( 'zipcode.yaml', 'w' )
yaml.dump( dict_data, savefile, default_flow_style=False, encoding='utf8', allow_unicode=True )
$ python zipcode.py

駅データのYAML

利用規約 | 駅データ 無料ダウンロード 『駅データ.jp』 はてなブックマーク - 利用規約 | 駅データ 無料ダウンロード 『駅データ.jp』
CodePlus はてなブックマーク - CodePlusさんが提供している駅データ.jpですが、利用規約に書かれている第4条 (利用)/第5条 (加工)/第6条 (第三者提供)の項目が利用者フレンドリーで素晴らしく思います。敬意を表したいと思います。こちらも生成したYAMLファイルをGithubに上げました。

DataFormat/SampleData
県名:
  路線名:
     駅名:
       station_code:駅名コード
       station_lat:駅の緯度
       station_lon:駅の経度
新潟県: 
  JR上越線: 
    上牧: 
      station_code: 1134213
      station_lat: 36.735616
      station_lon: 138.984533
    上越国際スキー場前: 
      station_code: 1134223
      station_lat: 37.028754999999997
      station_lon: 138.82797299999999
    五日町: 
      station_code: 1134226
      station_lat: 37.119900000000001
      station_lon: 138.90834599999999
    井野: 
      station_code: 1134203
      station_lat: 36.357456999999997
      station_lon: 139.023247
generate YAML
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 地域情報のYAML化
# transit.pyとして保存する

import time,urllib,urllib2,zipfile,os,yaml,xml.dom.minidom
base_url = 'http://www.ekidata.jp/api/'
base_pref_url = base_url + 'p/'
base_line_url = base_url + 'l/'
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.ekidata.jp/'
opener.addheaders = [( 'User-Agent', ua ),( 'Referer', referer )]
dict_data = {}
for i in range(1,48):
   pref_url = base_pref_url + str( i ) + '.xml'
   try: 
      pref_content = opener.open( pref_url ).read()
      pref_dom = xml.dom.minidom.parseString( pref_content )
      pref = pref_dom.getElementsByTagName( 'pref' )[0]
      pref_code = pref.getElementsByTagName( 'code' )[0].firstChild.data
      pref_name = pref.getElementsByTagName( 'name' )[0].firstChild.data 
      lines = pref_dom.getElementsByTagName( 'line' )
      for line_data in lines:
         try:
            time.sleep(0.5)
            line_code = line_data.getElementsByTagName( 'line_cd' )[0].firstChild.data
            line_name = line_data.getElementsByTagName( 'line_name' )[0].firstChild.data
            line_url = base_line_url + str( line_code ) + '.xml'
            line_content = opener.open( line_url ).read()
            line_dom = xml.dom.minidom.parseString( line_content )
            stations = line_dom.getElementsByTagName( 'station' )
            for station in stations:
               station_code = station.getElementsByTagName( 'station_cd' )[0].firstChild.data
               station_name = station.getElementsByTagName( 'station_name' )[0].firstChild.data
               station_lat  = station.getElementsByTagName( 'lat' )[0].firstChild.data
               station_lon  = station.getElementsByTagName( 'lon' )[0].firstChild.data
               dict_data.setdefault( pref_name, {} ).setdefault( line_name, {} ).setdefault( station_name, {} )
               dict_data[pref_name][line_name][station_name][ 'station_code' ] = int( station_code.encode( 'utf-8' ) )
               dict_data[pref_name][line_name][station_name][ 'station_lat' ] = float( station_lat.encode( 'utf-8' ) )
               dict_data[pref_name][line_name][station_name][ 'station_lon' ] = float( station_lon.encode( 'utf-8' ) )
         except Exception, e:
            print str(e)
            continue
   except Exception, e:
      print str(e) 
      continue
savefile = open( 'transit.yaml', 'w' )
yaml.dump( dict_data, savefile, default_flow_style=False, encoding='utf8', allow_unicode=True )
$ python transit.py