mk-mode BLOG

このブログは自作の自宅サーバに構築した Debian GNU/Linux で運用しています。
PC・サーバ構築等の話題を中心に公開しております。(クローンサイト: GitHub Pages

ブログ開設日2009-01-05
サーバ連続稼働時間
Reading...
Page View 合計
Reading...
今日
Reading...
昨日
Reading...

Ruby on Rails - 郵便番号検索システム修正!

[ サーバ構築, プログラミング ] [ MySQL, Rails, Ruby ]

こんばんは。

以前、日本郵便提供の郵便番号データ(CSVデータ)を使って以下の作業をしました。

しかし、日本郵便提供の郵便番号データ(CSVデータ)は仕様上非常に危険なデータとなっています。 日本郵便サイトの情報の転載は禁止されているので、ここには仕様を転載できません。 郵便番号データの説明 をご覧ください。

Ruby や Rails で作業するに当たって、当然この仕様のことは承知の上でしたが、個人レベルで使用するには支障がなかったので対応しておりませんでした。

最近この郵便番号データが危険であることについてコメントを頂いたこともあり、今回の改修作業に踏み切りました。 ※ちなみに、どうしても自動での対応が出来ないものもあります。

※以下に登場する「郵便番号」は全て7桁の郵便番号のことを示しています。

以下に記録します。

データの仕様から判明する事実

データの仕様に目を通したり、データを目で見て判明した重要な事実です。

  • 提供されているデータは文字コードに Shift-JIS 、文字セットに JIS X0208-1983 を使用しているため、定義されていない漢字はひらがなで設定されている。
  • 町域名フリガナが76文字を超える、または、町域名漢字が38文字を超える場合は複数レコードに分割されている。
  • 全国地方公共団体コード毎に、"イカニケイサイガナイバアイ"("以下に掲載がない場合")、"○○ノツギニバンチガクルバアイ"("○○の次に番地がくる場合")、五十音順となっている。(但し、町域名が長いために分割される場合は五十音順ではなく連続して配置されている)
  • 上記3のようにソートされているため、同じ郵便番号でも不連続となっているものが多数ある。

問題点

【問題点1】

  • 実際は漢字なのに、ひらがなで表示されているものがある。

【問題点2】

  • 「一つの郵便番号で二以上の町域を表す場合の表示」が「0」(非該当)にも関わらず同じ郵便番号が連続して重複する場合は町域名の文字列長が長いことより分割されているということなので、無条件に結合すればよい。
  • しかし、「一つの郵便番号で二以上の町域を表す場合の表示」が「1」(該当)の場合は、本来は結合する必要はないが、それらのレコードの中に町域名の文字列長が長いことより分割されているものも存在する。
  • これを判断するフラグが存在しないため、人間の目で見て判別する必要がある。

上記の問題点を解消するための事前調査

2011/11/28付のデータ(レコード件数:123,048件)を使用して検証してみました。

●「一つの郵便番号で二以上の町域を表す場合の表示」が「0」(非該当)で「郵便番号」が連続して重複しているものを検証

重複 件数
なし 122,498
2件 166
3件 38
4件 13
5件 2
6件 3
8件 3
【例】(8件重複している例)

1
2
3
4
5
6
7
8
9
10
11
12
  ====< 途中省略 >====
26102,"602  ","6020056","キョウトフ","キョウトシカミギョウク","キタフナハシチョウ","京都府","京都市上京区","北舟橋町",0,0,0,0,0,0
26102,"602  ","6028368","キョウトフ","キョウトシカミギョウク","キタマチ","京都府","京都市上京区","北町(上の下立売通天神道西入上る、上の下立売通御前西入、上",0,0,0,0,0,0
26102,"602  ","6028368","キョウトフ","キョウトシカミギョウク","キタマチ","京都府","京都市上京区","の下立売通御前西入上る、上の下立売通御前西入2丁目、上の下立売通御前西入",0,0,0,0,0,0
26102,"602  ","6028368","キョウトフ","キョウトシカミギョウク","キタマチ","京都府","京都市上京区","2筋目、下長者町通御前西入、天神道上の下立売上る、天神道仁和寺街道下る、",0,0,0,0,0,0
26102,"602  ","6028368","キョウトフ","キョウトシカミギョウク","キタマチ","京都府","京都市上京区","天神道下立売上る、天神道妙心寺道上る、天神道妙心寺道上る西入、仁和寺街",0,0,0,0,0,0
26102,"602  ","6028368","キョウトフ","キョウトシカミギョウク","キタマチ","京都府","京都市上京区","道天神道西入下る、仁和寺街道天神道東入下る、御前通上の下立売上る、御前通",0,0,0,0,0,0
26102,"602  ","6028368","キョウトフ","キョウトシカミギョウク","キタマチ","京都府","京都市上京区","上の下立売上る西入、御前通下立売上る、御前通下長者町上る西入、御前通仁",0,0,0,0,0,0
26102,"602  ","6028368","キョウトフ","キョウトシカミギョウク","キタマチ","京都府","京都市上京区","和寺街道下る西入、御前通妙心寺道上る西入、御前通西裏上の下立売上る、御前",0,0,0,0,0,0
26102,"602  ","6028368","キョウトフ","キョウトシカミギョウク","キタマチ","京都府","京都市上京区","通西裏下立売上る)",0,0,0,0,0,0
26102,"602  ","6028392","キョウトフ","キョウトシカミギョウク","キタマチ","京都府","京都市上京区","北町(御前通五辻上る、御前通今出川上る、御前通今出川上る1",0,0,0,0,0,0
  ====< 途中省略 >====


●「一つの郵便番号で二以上の町域を表す場合の表示」が「1」(該当)で「郵便番号」が連続して重複しているものを検証

重複 件数
なし 120,581
2件 476
3件 115
4件 35
5件 26
6件 10
7件 15
8件 9
9件 5
10件 5
11件 3
12件 1
13件 4
14件 1
15件 1
16件 2
17件 2
19件 1
20件 5
21件 1
22件 1
24件 1
25件 2
26件 1
27件 1
41件 1
46件 1
【例】(3件重複している例)

1
2
3
4
5
6
7
  ====< 途中省略 >====
28208,"678  ","6780072","ヒョウゴケン","アイオイシ","リュウセンチョウ","兵庫県","相生市","竜泉町",0,0,0,0,0,0
28208,"678  ","6780081","ヒョウゴケン","アイオイシ","ワカサノチョウアマウチ","兵庫県","相生市","若狭野町雨内",0,0,0,1,0,0
28208,"678  ","6780081","ヒョウゴケン","アイオイシ","ワカサノチョウイリノ","兵庫県","相生市","若狭野町入野",0,0,0,1,0,0
28208,"678  ","6780081","ヒョウゴケン","アイオイシ","ワカサノチョウウエマツ","兵庫県","相生市","若狭野町上松",0,0,0,1,0,0
28208,"678  ","6780082","ヒョウゴケン","アイオイシ","ワカサノチョウシモドイ","兵庫県","相生市","若狭野町下土井",0,0,0,1,0,0
  ====< 途中省略 >====


●「一つの郵便番号で二以上の町域を表す場合の表示」が「1」(該当)で「郵便番号」・「丁目を有する町域の場合の表示」が連続して重複しているものを検証 (「一つの郵便番号で二以上の町域を表す場合の表示」が同一でも「丁目を有する町域の場合の表示」が異なれば分けて考えることが可能であるため)

重複 件数
なし 120,798
2件 375
3件 110
4件 35
5件 26
6件 10
7件 15
8件 9
9件 5
10件 5
11件 3
12件 1
13件 4
14件 1
15件 1
16件 2
17件 2
19件 1
20件 5
21件 1
22件 1
24件 1
25件 2
26件 1
27件 1
41件 1
46件 1
【例】(2件重複している例)

1
2
3
4
5
6
  ====< 途中省略 >====
01631,"08005","0800564","ホッカイドウ","カトウグンオトフケチョウ","コマバキタマチ","北海道","河東郡音更町","駒場北町",0,0,0,1,0,0
01631,"08005","0800564","ホッカイドウ","カトウグンオトフケチョウ","コマバキタ1ジョウドオリ","北海道","河東郡音更町","駒場北1条通",0,0,1,1,0,0
01631,"08005","0800564","ホッカイドウ","カトウグンオトフケチョウ","コマバキタ2ジョウドオリ","北海道","河東郡音更町","駒場北2条通",0,0,1,1,0,0
01631,"08005","0800572","ホッカイドウ","カトウグンオトフケチョウ","コマバナミキ","北海道","河東郡音更町","駒場並木",0,0,0,0,0,0
  ====< 途中省略 >====

問題点の対応方法

【問題点1の対応】

  • 本来は漢字であるべきものがひらがなとなっているものについては、自動処理での対応は不可能。 (もともとひらがなであるかもしれないし、件数が多すぎるので個人のレベルでの手動修正もほぼ不可能。)

【問題点2の対応】

  • 「一つの郵便番号で二以上の町域を表す場合の表示」が「0」(非該当)にも関わらず同じ「郵便番号」が連続して重複する場合は町域名の文字列長が長いことより分割されているということなので、無条件に結合する。
  • 「丁目を有する町域の場合の表示」・「一つの郵便番号で二以上の町域を表す場合の表示」・「郵便番号」が連続して重複し「一つの郵便番号で二以上の町域を表す場合の表示」が「1」(該当)の場合は、、結合はしないが分割されている可能性があるので、その旨を把握できるようにする。(町域名の先頭にコメントを付加するなど) ※自分の目で見てデータを直接メンテナンスすることも可能。しかし、毎月修正がある郵便番号データを都度メンテナンスするのは事実上不可能。

という訳で、データベース(MySQL)取り込みの Ruby スクリプト、Ruby on Rails 製の検索アプリを修正しました。 実際には、結合可能なデータは結合し、分割されているかもしれないが自動判別が不可能なデータの町域名先頭に「※」マークを付加しました。

2011/11/28付のデータ(レコード件数:123,048件)で取り込み処理を実行した結果、計算どおりの 122,723件に集約できました。(検索アプリ(Rails)側はロジックの変更は無かったので、注意書きを修正しただけです)

以下で確認できます。

スナップショット

  • 「一つの郵便番号で二以上の町域を表す場合の表示」が「0」(非該当)で「郵便番号」が連続して重複しているもの。 無条件に結合して1件のデータとして扱えるようになりました。

POSTCODE_1

POSTCODE_2

  • 「一つの郵便番号で二以上の町域を表す場合の表示」が「1」(該当)で「郵便番号」・「丁目を有する町域の場合の表示」が連続して重複しているもの。 分割されていないデータだが、フラグだけでは自動判別不可能なため、「※」マークを付加している。 (同じ郵便番号なのに「※」マークが付加されていないデータは連続したデータでないから)

POSTCODE_3

  • 「一つの郵便番号で二以上の町域を表す場合の表示」が「1」(該当)で「郵便番号」・「丁目を有する町域の場合の表示」が連続して重複しているもの。 分割されているデータだが、フラグだけでは自動判別不可能なため、「※」マークを付加している。 (同じ郵便番号なのに「※」マークが付加されていないデータは連続したデータでないから)

POSTCODE_4

参考サイト等


Visual C# 版アプリも作っているので、対応しなければ・・・

以上。

Comments