日本郵便のcsv ( http://www.post.japanpost.jp/zipcode/download.html ) をデータベースへ突っ込んで利用するというのは昔なつかしの『入門Ajax』で書いたことがありますが、最近はNode.jsのCSVパーサーでいきなり利用するってこともできることに気づきました。
てことで、試してみます。
パッケージは、node-csv-parser
https://github.com/wdavidw/node-csv-parser
#インストール
npm install csv
#文字コードをどうするぅ?
日本郵便のcsvは、Shift_JISなのでutf-8へ直してやる必要があるんだけれど、node-iconvはまだ今一つで、実際に試してみるとやっぱりだめでした。
そこで、チャイルドプロセスのexecかspwanで直接iconvやnkfを使ってファイルのコード変換やろうってことで試したらうまくいきましたのでこれでいきます。
var csv = require('csv');
var exec = require('child_process').exec;
var zip = '3001626';//調べたい郵便番号
//入出力ファイル 08IBARAK.CSVから08IBARAK-utf8.CSVを作る
var infile = __dirname+'/08IBARAK.CSV';
var outfile = __dirname+'/08IBARAK-utf8.CSV';
//iconvコマンド
var cmd = 'iconv -f SHIFT_JIS -t UTF-8 -o '+outfile+' '+infile+'';
//文字コード変換 入力ファイルをUTF-8へ変換して出力後CSV処理起動
var child = exec(cmd,
function (error, stdout, stderr) {
getCSV();//CSV処理起動
if (error !== null) {
console.log('exec error: ' + error);
}
});
//CSV処理
function getCSV(){
console.time('bench');
csv()
.fromPath(outfile) //読み込むCSVファイル
.transform(function(data){//絞り込みと変換加工処理
if(data[2]===zip){
data[8]=
data[8]
.replace('以下に掲載がない場合','')
.replace('境町の次に番地がくる場合','')
return data[2]+ ' ' +data[6] +data[7] +data[8];
}
})
.on('data',function(data){
console.log(data);//変換後のデータを受け取り表示
console.timeEnd('bench');
})
.on('end',function(count){
console.log('Number of lines: '+count);
})
.on('error',function(error){
console.log(error.message);
})
}
#こうなった
$ node app.js
3001626 茨城県北相馬郡利根町四季の丘
Number of lines: 2856
速度はこの3000件で0.2秒かかってるので、文字コード部分は別処理にすべきかも。
まぁ、DBへ流し込む前のCSVパーサーとして使うのが普通かもしれないけれど、単体でもこんな風に絞り込みにも使えるわけなので、速度を気にしなければ日本郵便のデータ更新への対応のハードルが下がるというメリットもあるかも?
P.S. KEN_ALL.CSVの12万3千件の最後の沖縄の郵便番号9071801を検索したら、9166msだったので、まぁ、数万件ある場合は、やはり実用上はDBへ流し込んで使うべきですね(^^;;
P.S. ちなみに、文字コード変換後のファイルを作らずに、getCSV(stdout);で渡す手もあった。ただし、データが大きくなるとError: maxBuffer exceeded.となるので、たとえば、次のようにmaxBufferを大きくしてみた。
var cmd = 'iconv -f SHIFT_JIS -t UTF-8 '+infile+''
//入力ファイルをUTF-8へ変換して出力後CSV処理起動
var child = exec(cmd,{
maxBuffer: 20000*1024
},
function (error, stdout, stderr) {
console.log('stderr: ' + stderr);
getCSV(stdout);//CSV処理起動