|16| 使える郵便番号簿を自作する

|16| 使える郵便番号簿を自作する

by Guantare.com

私が実習を管理するためにシステムを作り始めた時にセキュリティの観点から閉じたネットワーク内で使うことを前提にしました。そうなるとWebを利用することができません。しかし、住所を入力する場面は沢山ありました。そして郵便番号が記入されていない住所もありました。仕方なく郵便番号簿を実装することにして、番号を入力すると住所を自動的に入力し、番号がわからない場合は住所から検索できるようにしました。日本郵政のKEN_ALL.csvにある “(” 以下を削除しただけの荒っぽいものでしたが、とても役立ちました。

もう少し丁寧に作り直そうと思って2018年に色々と悪戦苦闘しました。今回、さらに手を入れ直してみて、例外処理などあらためて気がついたところも多くありました。例外的な表記などはKEN_ALL.csvが更新される都度、変化する可能性が高いことをご了承ください。

追記 2021.1..21

2020.12.28更新のKEN_ALL.csvをダウンロードしてインポートしたら、”ビルの町域名の取得に失敗しました。例外的要素を検討して対処してください。スクリプトを中断します。”という素っ気無いダイアログが出て、処理を完了せずに終わってしまいました。どこのビルなのか調べてみると「海岸東京ポートシティ竹芝オフィスタワー」であることがわかりました。このビルのホームページを覗くと住所が「港区海岸一丁目7番1号」となっていますが、KEN_ALLの表記には「海岸東京ポート・・・」なのです。そして「海岸1丁目」には(次のピルを除く)という記述がありません。このビルは竣工が2020.5.29、開業が2020.9.14になっています。このページの初出が2020.6.30で微妙なタイミングです。

慌てて、ビルの町域名の例外的処理をスクリプトに追加しました。が、例外的な処理がされていない時の中断方法があまりにも不親切だと考え、うまく処理できなかったビルを検索してリスト表示するように改良しました。ダウンロードできるサンプルファイルは改良されたものです。

まずは、改良版のSampleDB_13_pstcd_051.zipをダウンロードしてください。

サンプルファイルの使い方

「y_郵便番号簿」というファイルが郵便番号のデータベースですが、データは入っていません。日本郵便のダウンロードページから「KEN_ALL.csv」というファイルをダウンロードしてインポートします。

https://www.post.japanpost.jp/zipcode/dl/kogaki-zip.html
から「全国一括」をダウンロードしてください。

KEN_ALL.csvをインポート

インポートを始めると一連のスクリプト が走り、データの内容を整理してくれます。

私のMacBook Air(2020 Core i5 1.1GHz クアッドコア メモリ16GB)で9分ぐらいかかりますので気長に待ってください。ただ、前に使っていたMacBook 12(2015 Core M 1.3GHz デュアルコア メモリ8GB)でも10分前後でインポートできたので高性能である必要はないかもしれません。

インポートを開始すると「開発」か「運用」かというダイアログが出ます。

KEN_ALL.csvをインポートして整理する作業用のテーブルと最終的に運用するデータを収めるテーブルに分かれています。運用だけだとそのためのテーブルがあれば問題ありませんのでそれ以外のテーブルのデータを削除します。
「運用」を選択すると約100MB、「開発」を選択すると約300MBになります。
「開発」では元のデータがどのように処理されたか確認することができます。

「市町村リスト作成」というボタンがあります。作成しなくても全く問題はありません。どれぐらいの市町村があるのかという興味から市町村リストを作ろうと思っただけです。これは12万件以上ある全てのレコードをループして市町村を抽出するのでKEN_ALL.csvのインポート・処理と同じぐらい時間がかかります。

「y_郵便番号簿」の使い方

「y_郵便番号簿」単体で番号や地域の検索ができます。

  • 都道府県、市町村と絞り込む方法。
  • 郵便番号を入力して地域を検索する方法。
  • 直接、住所を入力して郵便番号を検索する方法。

の3パターンがあります。
ファイル内にバーチャルリストのテーブルがありそれを利用して検索結果を表示しています。

都道府県からの絞り込み検索

「都道府県から検索」の右側のボタンをクリックすると都道府県のリストが表示されます。「市」か「町村」を選択します。東京都の場合は「23区」かそ「区以外」になります。

ファイルの中に「y02_都道府県」というテーブルがあり、既に都道府県名が入力されています。このデータを削除すると都道府県から絞り込み検索ができなくなるので注意してください。

高層ビルは階ごとに郵便番号が振られていて、件数が多くなりすぎるのでビルごとにまとめてあります。「>」ボタンでビルの階層リストへ移動できます。

区が設定されている市は区ごとにまとめてあります。
「>」ボタンで町域名リストへ移動できます。

それぞれの表示レベルに応じて五十音行ごとに絞り込めます。

郵便番号を入力して検索

郵便番号からの検索では郵便番号欄に番号を入力して右側のボタンをクリックすると検索されます。ハイフンは有っても無くても構いません。

京都市の通り名がある町域は「町名(通り名)」のパターンのほかに「町名」だけのレコードも表示するようにしてあります。これは「町名」だけのデータがあるのではなく、バーチャルリストで作成しています。
都道府県からの絞り込みでは「町名」だけのリストは表示されません。

住所を入力して番号を検索

住所からの番号検索では住所の入力欄に入力して右側のボタンをクリックします。番地まで入力されていても検索できます。

京都市では通り名を省略して入力すると同じ町域名が検索されます。「上京区一町目」では9件が検索され、3つの郵便番号があることがわかります。住所から郵便番号を調べるには通り名が分かっていないと調べられないことになります。

京都市の場合は「通り名」「町域名」の順に入力された住所でも、「町域名」「通り名」の順に入力された住所でも検索できるようになっています。

他のファイルから利用する

「郵便番号住所」ファイルの住所を入力するグローバルフィールドが配置されたテーブルと「y_郵便番号簿」のバーチャルリストをリレーションで関連付けることで「y_郵便番号簿」と同じ検索方法を利用できるようになります。

検索のスクリプト自体は「y_郵便番号簿」に書かれていますので、そのスクリプトを走らせるスクリプトを書くだけで様々なファイルからアクセスできます。

様々なプロジェクトの中で容易に利用できるのではないでしょうか。

「郵便番号住所」のホームから「郵便番号簿」をクリックします。

郵便番号から住所を検索

郵便番号欄に番号を入力するとトリガーにより検索が開始されます。
対象レコード数が1件で括弧などの記号がない場合は都道府県、市町村、町域名を自動的に入力します。1件で括弧がある場合と複数件の場合はポップオーバーでバーチャルリストを表示します。

このバーチャルリストは前回とは異なり、このファイルにはありません。「y_郵便番号簿」ファイルのバーチャルリストを利用しています。バーチャルリストを作成するスクリプトは「y_郵便番号簿」にあるので、それを走らせるためのスクリプトをこのファイルに書けばいいのです。
このファイルではポップオーバーの制御や入力に関してのスクリプトを書きます。

郵便番号フィールドから抜けた時にトリガーを設定してあります。前回のWebAPIを利用した仕組みの場合、マウスで抜けても問題がなかったのですが、今回はマウスで抜けると一瞬、ポップオーバーが開いてすぐに閉じてしまうようになりました。タブで抜けると問題なくポップオーバーは開いたままになります。

入力前と同じ番号を入力すると何もしない設定にしてあります。郵便番号欄が7桁に達したら抜けるようにトリガーを設定したところ、入力前と同じ番号を入力してもバーチャルリストを作成するスクリプトが走ってしまいました。同じ番号であるかどうかの判定が飛ばされているようです。1件だけの場合はポップオーバーは開かずに住所だけを入力する仕組みなのですが、番地まで入れてあると番地が消えてしまいます。

仕方がないので、7桁に達したらポップオーバーボタンではないオブジェクトに移動し、郵便番号が同じかどうか判定するスクリプトを走らせ、同じでなければバーチャルリストを作成して1件であればその住所を入力、複数あればポップオーバーを開くという2段階のスクリプトにしてあります。

前回は同じファイル内のバーチャルリストを使いましたが、今回は別のファイルにあるスクリプトとバーチャルリストを利用しています。はっきりとしたことは分からないのですが、挙動の違いはこれが原因かもしれません。

リストの中から該当する住所を選択し、左側の三角ボタンをクリックして入力する仕組みです。

KEN_ALL.csvで括弧で囲まれた町域名はそのまま括弧で囲んでリスト表示していますが、入力では括弧より前の文字列が入力されるようになっています。京都市の通り名は括弧で囲まれているのですが、これを入力するのは大変なので括弧を外した状態で入力されます。「通り名」「町名」の順にしてあります。

住所から郵便番号を検索

住所が分かっていて郵便番号が分からない時は住所から番号を検索できるようにしてあります。住所を入力したら「番号を検索」ボタンをクリックすると該当する住所とその郵便番号が表示されます。

ポップオーバーボタンは番号から住所を検索する時とは異なっていますが、バーチャルリストのポータルは全く同じものです。

1件の場合でもポップオーバーを開いて選択する仕組みにしてあります。
番地まで入力されいることもあるので、検索された住所の文字数と同じ文字数の入力されている住所を比較して同じであればそのままに、異なっていると番号だけを入力するか住所も書き換えるか選択するようになっています。

京都市の通り名は「町名、通り名」でも「通り名、町名」でも「町名」だけでも検索できるようになっています。

入力される文字列と検索結果の表示

バーチャルリストに表示される町域名は郵便番号簿で括弧で囲まれた部分は括弧で囲んで表示しますが、入力される値は括弧より前の文字列だけです。括弧で囲まれた部分をどう解釈したらいいのか分からない事例があるので、判断はユーザーに任せることにしました。少なくともユーザーは番地まで覚えているか、メモ書きなどがあるはずなので足りない部分は入力してもらおうという考えです。住所から郵便番号を検索する場合は(〇〇番地を除く)などの括弧内の情報がなければ判断が難しいとも思います。

ただ、いくつかの例外もあります。京都市の通り名は括弧内にあるのですが、長くて入力が面倒そうなので選択と同時に入力されるようにしてあります。

郵便番号簿とは何だろう?

郵便番号は1968年に導入されました。最初は3桁もしくは5桁だったと思います。始まったばかりの頃は郵便物を出すのに近くの郵便局へ出向いて「郵便番号簿」という冊子を開いて番号を調べたものです。今でこそコンピュータで調べることができますが、日本郵便が出しているCSVファイルは紙に印刷する原稿のようなものです。複数の町域にまたがる郵便番号は町域名を読点で区切り、複数の町域名を括弧で囲む、紙は横幅に限界がありますから1行で収まらなければ複数行に分ける、という感じです。
ですから「次に…」とか「上記に…」、「以外」というようなコンピュータには馴染まない表現があるのだと思います。

この1行に収まらなければ複数行にというのが最大の特徴ではないでしょうか。

そもそも住所から番号を調べるのが郵便番号簿の役割であり、番号から住所を調べることは無かったのです。

郵便番号に使われている記号

”()”、”「」”、”、”、”〜”、”・”の記号が使われています。

”()”は(その他)のような但し書きや(糠森、小野松)のように複数の地名を併記する場合に使われ、”「」”は”()”の中にさらに括弧書きするときに”()”の代用として使われているケースが多いです。

“、”は複数の地名を併記する時の区切り文字として使われています。

“〜”は(7〜13丁目)のように番地などが続いているときに使われています。

“・”は(4丁目1〜2番・10〜27番、5丁目)のような表記で(4丁目1〜2番)、(4丁目10〜27番)、(5丁目)の意味ではないでしょうか。他の表記方法もあるのではっきりとはわかりません。

  • いわき市 勿来町(大高)
  • いわき市 勿来町(窪田)
  • いわき市 勿来町(九面)

  • 会津若松市 高野町上沼
  • 会津若松市 高野町上高野
  • 会津若松市 高野町木流

など括弧があるものと無いものがあります。括弧付きの地名は省略してもいいのか、括弧内の地名がある地域とない地域に分かれているのか、よくわかりません。

地名ではない文字列

“その他”、”除く”、”以外”、”以降”、”(無番地)”、”(番地のみ)”、”(番地)”、”(丁目)”、”(大字)”、”(大字、番地)”、”及び”、”以上”、”以下に掲載がない場合”、”次のビルを除く”、 ”の次に番地がくる場合”、”一円”などが使われています。

ただ、滋賀県多賀町に”一円”という地名がありますので注意が必要です。”以下”という2文字が単独で使われている例はありませんが、長崎市に”以下宿町(イガヤドマチ)”という地名があります。

解釈が難しい表記

記号や地名でない文字列の使い方から、そのルールを憶測することができるのですが、全てがそのルールには当てはまらないようです。

愛知県豊橋市

豊橋市高師町はGoogleマップで調べると7〜8ヶ所の飛地が検索され複雑です。

その中で

441-8156 高師町(北原1、1-57、58、76、80〜86、44番地)
440-0845 高師町(北原、その他)
440-0845 高師町(その他)

と記述された3行がKEN_ALL.csvにあります。
「高師町北原」をGoogleマップで検索すると3ヶ所の飛び地が表示されました。

高師町(北原1番地)(北原1-57番地)(北原58番地)(北原76番地)(北原80〜86番地)(北原44番地)

と考えると最後の番地がその前の番地より小さくなってしまいます。

高師町(北原1番地)(北原1-57番地)(北原1-58番地)(北原1-76番地)(北原1-80〜86番地)(北原44番地)

と考えると数字自体は後へ行くほど大きくなるのですが、(北原1-80〜86番地)以前は(北原1番地)に含まれるのではと思います。

それ以外の(北原)は(北原、その他)になるはずですが、他の事例に当てはめると(北原「その他」)という表記にすべきかなと考えます。
それと高師町(その他)あると考えられます。

同じ豊橋市で

440-0833 豊橋市 飯村町西山、高山
440-0032 豊橋市 岩田町居村、北郷中
440-0041 豊橋市 岩田町宮下、道合

という3件がありますが、”豊橋市高山”をGoogleマップで調べると”豊橋市飯村町高山”と表示されます。他の2件も同様なので

440-0833 豊橋市 飯村町(西山、高山)
440-0032 豊橋市 岩田町(居村、北郷中)
440-0041 豊橋市 岩田町(宮下、道合)

なのではないでしょうか。

香川県土庄町

香川県土庄町(トノショウマチ)では”甲、乙(〇〇)”という表記が11件あり、全て郵便番号が異なっています。Googleマップで住所を入力して調べると”甲〇〇”という町域は地図上で検索されますが、”乙〇〇”という町域は検索されません。”土庄町乙”なら1ヶ所検索されますがとても狭い地域です。

“土庄町甲”で検索した土庄町甲全域です。その中のオレンジ色にした部分が”土庄町乙”で検索した時の地域です。

どう読み解けばいいのかわからないので”、”の処理はせず、そのままにしてあります。

ちょっと面白いこと

「府中」あるいはそれに類する地名は日本全国にあると思います。試しに「府中市府中町」を検索すると東京都と広島県がヒットしました。もちろん郵便番号も異なります。

ただ、都道府県、市区町村、町域名が全く同じで郵便番号も同じという地域が2ヶ所あります。

581-0027 大阪府八尾市八尾木
673-0012 兵庫県明石市和坂

どのような理由でこの2ヶ所が2件づつデータがあるのか調べました。町域名のヨミが2通りあったのです。
「八尾木」は「ヤオギ」と「ヨオギ」、「和坂」は「カニガサカ」と「ワサカ」となっていました。郵便番号も同一なので問題はないのでしょう。

950-3323 新潟市北区東栄町
950-3104 新潟市北区東栄町

という町域名が同じで郵便番号が異なっているところがあります。Googleマップを使って郵便番号で検索すると離れた場所にそれぞれ表示されました。

ヨミも違っていて「950-3323」の方が「トウエイチョウ」、「950-3104」の方が「ヒガシサカエマチ」になっていました。

これだと住所から番号を検索したときにどちらの番号にするか選択できない状態になるのでサンプルでは括弧書きでヨミを入れることにしました。

日本郵便のWebサービス

日本郵便のサイトで郵便番号から住所を検索すること、住所を入力して郵便番号を調べることができます。

ハイフンが入っているとエラーになるのでハイフンなしで郵便番号を入力して検索すると京都市の通り名のように複数行に渡っているところは1件にまとめられて表示されます。これはこれでいいのですが、”、”で区切られているところは複数行に表示した方が視覚的に分かりやすくていいのにと思います。

“6028134” で検索すると

京都市上京区一町目(大宮通椹木町下る、大宮通丸太町上る、椹木町通大宮西入、丸太町通大宮東入)

の1件が戻ってきます。これはKEN_ALL.csvでは2行になっています。

住所を入力して郵便番号を調べるのは番地まで入力してしまうと「該当する地名を特定できませんでした。再度検索を行ってください。」と叱られてしまいます。

 “( )” 付きの住所はさらに難しい要素があります。
上記の京都市を例にとると

“京都市上京区一町目大宮通椹木町下る” で検索するとエラーになります。
“京都市上京区一町目(大宮通椹木町下る” で検索しなければなりません。
2区切り目の “大宮通丸太町上る” では括弧を入れて
“京都市上京区一町目(大宮通丸太町上る” にしなければいけません。

これは京都市に限らず括弧付きの他の住所でも同じです。
どこに括弧を入れるべきか知らなければ郵便番号を調べられないことになります。番地まで入力するとエラーを起こすことも考えるととても不親切なサービスだと感じます。

元々、郵便番号簿は住所から郵便番号を探す目的で作られているはずですから、もう少し親切な仕組みにしてもらいたいものです。

サンプルファイルの処理手順

サンプルの “y_郵便番号簿” について概略を説明しますが、その前に考え方について。

y_郵便番号簿での考え方

このファイルは他のファイルからの問い合わせに対して少ない労力で応答できるように考えました。「y_郵便番号簿」 に手を加えなくても利用できるようにしてあります。他のファイルからは 「y_郵便番号簿」 の 「yv01_VL_検索」 というバーチャルリストのテーブルだけにリレーションを張り、他のファイルからスクリプトを走らせることで汎用性を持たせてあります。

「y_郵便番号簿」 の 「yk01_郵便番号簿」テーブルにKEN_ALL.csvをインポートし、作業用テーブルとして利用します。作業が終われば 「y01_郵便番号簿」 に必要な項目をインポートして運用していきます。他のファイルからの応答はバーチャルリストにして返します。

サンプルファイルでは前述したように検索結果として表示される町域名は括弧付きで表示し、入力される値は括弧より前の町域名を入力するようにしています(京都の通り名は例外)。サンプルファイルでは検索結果表示用のフィールドと入力用のフィールド、住所から番号を検索するための住所フィールドを持たせてあります。

原則として検索結果表示用のフィールドは町域名の次に括弧書きを入れ、入力用フィールドは括弧なしの町域名、番号検索用のフィールドは検索結果表示用から括弧をなくしたものにしてあります。

番地まで入力されている住所から番号を検索する方法として、入力されている文字列で検索して、対象レコードが無ければ文字列の最後から一文字づつ削って検索し直します。対象レコードが出てくるまでループさせています。

処理手順

最初に同一の郵便番号を調べてその親レコードを別テーブルに作っておきます。

コンピュータが計算するときに対応が難しい例外に前もって処理をしています。これはKEN_ALL.csvの内容が変われば修正が必要になる部分です。

次にビル名やビル所在地の町域名、ビルに関する括弧などを処理していきます。

そして、KEN_ALL.csvの特徴である複数行にわたる記述を、最初に作った同一番号の親レコードを利用して1行にしていきます。

“( )” 内の “、” 区切りを利用して新たなレコードを追加します。
“(1丁目、2丁目「651、662、668番地」以外、3丁目)” のような表記が多いので “「 」” 内の “、” は区切り文字として扱わない処理をしておきます。

“( )” 内の内容が地名や番地なのか、 “(その他)” のような地名ではない文字列なのかを判断します。これは検索結果表示には必要ですが、住所から検索するときのデータとしては不要だからです。

京都市の通り名のチェックをして、最初に施した例外処理の文字列をもとに戻しておきます。

最後に必要な項目を 「y01_郵便番号簿」 にインポートします。

処理したデータの確認

インポート手順で「開発」か「運用」かを選択すると書きましたが、「運用」を選択すると作業用テーブルのデータは削除されます。「開発」だと削除されず、ホーム画面に「処理データ確認」ボタンが表示されます。
クリックして確認画面に移動します。

このリストでは作業用テーブルのレコードのうち追加されたレコードと複数行あるレコードの2行目以降は表示されません。

様々な記号や地名でない文字列、気になる地域がボタンで検索できます。各レコード右側の拡大ボタンをクリックすると作業用レコードと運用テーブルのレコードが表示され、どのように処理されたのか確認することができます。
拡大ボタンの左側の数字は運用テーブルのレコード数です。

ヘッダ部分は作業用レコードで複数行に渡っているものは複数のレコードが表示されます。ボディ部分が運用レコードで、左側から、入力用データ、検索結果表示データ、住所から検索されるデータになっていて、記号や地名でない文字列の処理を確認することがきます。
右上の「○行」が複数行になっているKEN_ALL.csvのレコード数、左上の「○件」が処理された運用テーブルのレコード数です。

ボタンでの検索では検索範囲が限られています。
“「 」” ボタンで検索された1行目は

北海道 余市郡仁木町 大江(1丁目、2丁目「651、・・・・)

になっています。 余市郡仁木町 大江 の他の地域はどうなのか確認しなければならないこともあるので検索モードにして検索することもできます。この時も追加されたレコードと複数行あるレコードの2行目以降は表示されないよう、レイアウトにトリガーを設定してあります。

“大江” という地名は多くあるみたいですが、さらに “余市郡仁木町” で絞り込めばいいでしょう。
北海道 余市郡仁木町 大江 はKEN_ALL.csvでは2件、それぞれが運用テーブルのレコードでは3件と2件、合計5件に処理されています。片方には “「 」” があり、他方は “、” だけです。

●   ●   ●

2年前、郵便番号簿に手をつけ始めた頃はできるだけ括弧を減らして入力を積極的に補助しようと悪戦苦闘していました。同一郵便番号で町域名が同じところはもちろん、括弧の中の地名で共通する部分だけを抜き出したり、同じ町域名で異なる郵便番号のリストを作ったりでテーブルの数が増え、リレーションも複雑になっていました。今回は複雑になったリレーションやテーブルをシンプルに整理しました。また、以前は気がつかなった例外的な表記の処理も含めてスクリプトも整理しました。20個ほどのスクリプトを半分にしています。整理しきれていないところもあり、余計なスクリプトステップが残っているかもしれません。

やはり郵便番号の整理は難しいですし、例外的な表記法も地域特有のものだったり、その土地を知らなければ理解できないようなものだったりと人間臭さを多いに感じながらの作業でした。


夕方の散歩。残照が北の空を青く照らし、建物の灯りが美しく輝きます。
iPhone 11 Pro  4.20mm  ISO640  1/30  F1.8  0.0EV  P
heif
2020/3 Kodaira City