[ヅ] Node.js でバッチプログラムを開発する (2015-03-29) で作ったプログラムの焼き直し。

緯度・経度から住所への変換には YOLP(地図):Yahoo!リバースジオコーダAPI - Yahoo!デベロッパーネットワーク を利用する。

環境: Mac OS X Yosemite + Node.js


$ uname -mrsv
Darwin 14.3.0 Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64 x86_64

$ node --version
v0.10.29

作成したファイルは3つ

  • package.json (バッチプログラムの設定ファイル)
  • app.js (バッチプログラムのメインファイル)
  • reverse_geocoder.js (緯度・経度を住所へ変換するモジュール)

package.json

今回は HTTP 通信の処理を手軽に書きたいので request モジュールを使う。

package.json の書き方は npm package.json 日本語版 取扱説明書 が参考になる。


$ cat package.json 

{
  "name": "address-getter",
  "version": "0.0.1",
  "description": "address getter",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "author": "nilab",
  "dependencies": {
    "request": "^2.55.0"
  }
}

メインのスクリプト app.js

緯度・経度をリバースジオコーダに渡して、住所へ変換する。


$ cat app.js 

// 緯度・経度のリスト
var list = [
  [35.170608,  136.882315], // 名古屋駅
  [35.444415,  139.640174], // 横浜公園 
  [35.911567,  140.182261], // 茨城県龍ケ崎市
  [20.425602,  136.081200], // 沖ノ鳥島
  [33.912891,  107.344120], // 中国
  [37.733883, -122.383787], // アメリカ
  [24.812141,   79.812915], // インド
  [        0,           0]
];

// WebAPIコール用のアプリケーションID
var appid = '<YOUR APPLICATION ID (自分のappidを指定する)>';

// リバースジオコーダオブジェクトを取得  
var revgeo = require('./reverse_geocoder');
var rg = revgeo.getReverseGeocoder(appid);

// 緯度経度を住所文字列に変換
list.forEach(function(latlon){
  rg.getAddress(latlon[0], latlon[1], function(address, err, res){
    if(address){
      console.log(
        latlon[0] + ',' +
        latlon[1] + ' => ' +
        address.getText());
    }else{
      console.log('error: ' + err);
      console.log('status code: ' + res.statusCode);
    }
  });
}, this);

緯度・経度を住所へ変換する reverse_geocoder.js

緯度・経度を YOLP(地図):Yahoo!リバースジオコーダAPI に渡して、住所文字列へ変換する。


$ cat reverse_geocoder.js 

var request = require('request');
var querystring = require('querystring');

// リバースジオコーダオブジェクト
// appid: WebAPIコール用のアプリケーションID
function ReverseGeocoder(appid){
  this.appid = appid;
}

// 住所オブジェクトを返す
// lat: 緯度
// lon: 軽度
// callback: コールバック関数
ReverseGeocoder.prototype.getAddress = function(lat, lon, callback){

  // クエリー文字列を組み立てる
  var qs = querystring.stringify({
    lat: lat,
    lon: lon,
    output: 'json',
    appid: this.appid
  });

  var url = 'http://reverse.search.olp.yahooapis.jp/OpenLocalPlatform/V1/reverseGeoCoder?' + qs;

  var opts = {
    url: url,
    json: true // JSONレスポンスを自動処理する設定
  };

  // Web API をコールする
  request.get(opts, function(error, response, body){

    if(!error && response.statusCode == 200){
      // JSONレスポンスがJavaScriptオブジェクトに変換されて
      // 変数bodyに入っている
      callback(new Address(body));
    }else{
      callback(null, error, response);
    }
  });
};

// 住所オブジェクト
function Address(data){
  this.data = data;
}

// 住所文字列を返す(シンプル)
Address.prototype.getSimpleText = function(){
  return this.data.Feature[0].Property.Address;
};

// 住所文字列を返す
Address.prototype.getText = function(){

  if(this.data.ResultInfo.Count === 0){
    // 住所が見つからない場合
    return '';
  }

  var property = this.data.Feature[0].Property;

  if(property.Country.Code == 'JP'){

    // 日本の場合
    return property.AddressElement

      .filter(function(x){
        // 都道府県・市区町村・大字の住所レベル項目だけ残す
        switch(x.Level){
          case 'prefecture':
          case 'city':
          case 'oaza':
            return true;
          default:
            return false;
        }
      }, this)

      .map(function(x){
        // 住所レベル項目の名称
        return x.Name;
      },this)

      .join(''); // 住所レベル項目の名称をつなげる
  }else{

    // 日本以外
    if(property.Address){
      return property.Country.Name + ' ' + property.Address;
    }else{
      return property.Country.Name;
    }
  }
};

// リバースジオコーダオブジェクトを取得する
// appid: WebAPIコール用のアプリケーションID
function getReverseGeocoder(appid){
  return new ReverseGeocoder(appid);
}

module.exports = {
  getReverseGeocoder: getReverseGeocoder
}

npm install で必要なパッケージをインストール

npm install コマンドは、 package.json の dependencies の内容を見て、必要なパッケージをインストールしてくれる。


$ npm install
npm WARN package.json address-getter@0.0.1 No repository field.
npm WARN package.json address-getter@0.0.1 No README data
request@2.55.0 node_modules/request
├── caseless@0.9.0
├── json-stringify-safe@5.0.0
├── aws-sign2@0.5.0
├── forever-agent@0.6.1
├── stringstream@0.0.4
├── oauth-sign@0.6.0
├── tunnel-agent@0.4.0
├── isstream@0.1.2
├── node-uuid@1.4.3
├── qs@2.4.1
├── combined-stream@0.0.7 (delayed-stream@0.0.5)
├── mime-types@2.0.10 (mime-db@1.8.0)
├── http-signature@0.10.1 (assert-plus@0.1.5, asn1@0.1.11, ctype@0.5.3)
├── form-data@0.2.0 (async@0.9.0)
├── bl@0.9.4 (readable-stream@1.0.33)
├── tough-cookie@0.13.0 (punycode@1.3.2)
├── hawk@2.3.1 (cryptiles@2.0.4, sntp@1.0.9, boom@2.7.1, hoek@2.12.0)
└── har-validator@1.6.1 (commander@2.8.0, chalk@1.0.0, bluebird@2.9.24, is-my-json-valid@2.10.1)

npm start コマンドで実行

実行方法を package.json の scripts start の項目に書いておくと、 npm start コマンドで実行できる。


$ npm start
 
> address-getter@0.0.1 start /Users/alice/hogehoge
> node app.js

33.912891,107.34412 => 中華人民共和国 陝西省
35.911567,140.182261 => 茨城県龍ケ崎市寺後
35.444415,139.640174 => 神奈川県横浜市中区横浜公園
35.170608,136.882315 => 愛知県名古屋市中村区名駅
20.425602,136.0812 => 東京都小笠原村沖ノ鳥島
37.733883,-122.383787 => アメリカ合衆国 カリフォルニア州
24.812141,79.812915 => インド
0,0 => 

無事に、緯度と経度を住所へ変換できた。

非同期処理なので、リストの順番に結果が返ってくるとは限らない (実際にちがう順で住所文字列が返ってきている)。

参考資料

tags: node.js

Posted by NI-Lab. (@nilab)