KEN_ALLってなあに


:::note info
2023/07　追記
長年、改善の雰囲気すらなかったKEN_ALLですが、国会で住所の正規化が話題になった為か、ついに新フォーマットが登場しました！
https://forest.watch.impress.co.jp/docs/serial/yajiuma/1514142.html
本記事は旧フォーマットでの話となりますのでご了承ください。
:::


<img width="200" alt="tegami_yagi_black" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/852059/6a490f6a-6543-60c0-c486-cdcd2ecee034.png">


こんにちは。Japan Digital Design のインフラチームに所属している渡邉です。
有志で AdventCalendar をやっており、今回は18日目の記事です。
https://adventar.org/calendars/5160

もう長いことこの業界で働いており、20代のころの仕事はほとんど思い出せないくらい、技術の移り変わりや進歩の速さに追いつけず勉強の日々ですが、昔と変わらぬ懐かしい佇まいで存在し続けるものも中にはあります。それがKEN_ALL...

住所を扱う仕事をしたことがある方なら避けては通れない、あの悪名高い（？）KEN_ALLですが、2020年現在どうなってるかなーと久々に覗いてみたところ案の定ほぼ変わっておらず（10数年のうちに途中で圧縮形式がlzhからzipになったりと微妙に変わってはいますが）、いまさら特に新たなネタもないのですが、知らないよ、という方のためにおさらいしてみようと思います。



# KEN_ALLとは

日本郵便のサイトにて配布されている、郵便番号と住所が記載されたCSVデータのことです。
https://www.post.japanpost.jp/zipcode/download.html
Webサイトの入力フォームやアプリなどで郵便番号から住所を自動補完する場合などによく使われるかと思います。
CSVデータは各都道府県ごと、および全国（全都道府県）のデータがあり、全国のデータをダウンロードして解凍すると現れるのがKEN_ALL.csvです。
中身はこんな感じ↓

```
01101,"060  ","0600000","ﾎｯｶｲﾄﾞｳ","ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ","ｲｶﾆｹｲｻｲｶﾞﾅｲﾊﾞｱｲ","北海道","札幌市中央区","以下に掲載がない場合",0,0,0,0,0,0
01101,"064  ","0640941","ﾎｯｶｲﾄﾞｳ","ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ","ｱｻﾋｶﾞｵｶ","北海道","札幌市中央区","旭ケ丘",0,0,1,0,0,0
01101,"060  ","0600041","ﾎｯｶｲﾄﾞｳ","ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ","ｵｵﾄﾞｵﾘﾋｶﾞｼ","北海道","札幌市中央区","大通東",0,0,1,0,0,0
01101,"060  ","0600042","ﾎｯｶｲﾄﾞｳ","ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ","ｵｵﾄﾞｵﾘﾆｼ(1-19ﾁｮｳﾒ)","北海道","札幌市中央区","大通西（１～１９丁目）",1,0,1,0,0,0
01101,"064  ","0640820","ﾎｯｶｲﾄﾞｳ","ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ","ｵｵﾄﾞｵﾘﾆｼ(20-28ﾁｮｳﾒ)","北海道","札幌市中央区","大通西（２０～２８丁目）",1,0,1,0,0,0
```

日本郵便のサイトにもありますが下記のルールで生成されています。

> * 全角となっている**町域部分の文字数が38文字を越える場合**、また半角となっている**フリガナ部分の文字数が76文字を越える場合**は、複数レコードに分割しています。
* この郵便番号データファイルでは、以下の順に配列しています。

> 1. 全国地方公共団体コード（JIS X0401、X0402）………　半角数字
1. （旧）郵便番号（5桁）………………………………………　半角数字
1. 郵便番号（7桁）………………………………………　半角数字
1. 都道府県名　…………　半角カタカナ（コード順に掲載）　（注1）
1. 市区町村名　…………　半角カタカナ（コード順に掲載）　（注1）
1. 町域名　………………　半角カタカナ（五十音順に掲載）　（注1）
1. 都道府県名　…………　漢字（コード順に掲載）　（注1,2）
1. 市区町村名　…………　漢字（コード順に掲載）　（注1,2）
1. 町域名　………………　漢字（五十音順に掲載）　（注1,2）
1. **一町域が二以上の郵便番号で表される**場合の表示　（注3）　（「1」は該当、「0」は該当せず）
1. **小字毎に番地が起番されている町域**の表示　（注4）　（「1」は該当、「0」は該当せず）
1. 丁目を有する町域の場合の表示　（「1」は該当、「0」は該当せず）
1. **一つの郵便番号で二以上の町域を表す**場合の表示　（注5）　（「1」は該当、「0」は該当せず）
1. 更新の表示（注6）（「0」は変更なし、「1」は変更あり、「2」廃止（廃止データのみ使用））
1. 変更理由　（「0」は変更なし、「1」市政・区政・町政・分区・政令指定都市施行、「2」住居表示の実施、「3」区画整理、「4」郵便区調整等、「5」訂正、「6」廃止（廃止データのみ使用））

> ※1 文字コードには、MS漢字コード（SHIFT JIS）を使用しています。
※2 文字セットとして、JIS X0208-1983を使用し、規定されていない文字はひらがなで表記しています。
※3 **「一町域が二以上の郵便番号で表される場合の表示」**とは、町域のみでは郵便番号が特定できず、丁目、番地、小字などにより番号が異なる町域のことです。
※4 **「小字毎に番地が起番されている町域の表示」**とは、郵便番号を設定した町域（大字）が複数の小字を有しており、各小字毎に番地が起番されているため、町域（郵便番号）と番地だけでは住所が特定できない町域のことです。

> <小字に同一番地が存在する住所>
○○市△△町が郵便番号の表す範囲であり、町域（郵便番号）と番地だけでは住所が特定できません。

> ○○市△△町字A100番地
 ○○市△△町字B100番地
 ○○市△△町字C100番地

> ※5 **「一つの郵便番号で二以上の町域を表す場合の表示」**とは、一つの郵便番号で複数の町域をまとめて表しており、郵便番号と番地だけでは住所が特定できないことを示すものです。
※6 「変更あり」とは追加および修正により更新されたデータを示すものです。
※7 全角となっている町域名の文字数が38文字を超える場合、また、半角カタカナとなっている町域名のフリガナが76文字を越える場合には、複数レコードに分割しています。

なんだか色々と書いてありますが、使用する際に困るのは主に太字の部分、さらにはここに記載のない事項によるものが多いです。



# KEN_ALLの困るところ
文字コードが Shift-JIS なのも「え！？」って思う方もいらっしゃるかもしれませんが、まあこれは序の口。
表現できない漢字はひらがなになってますが、それが許容できれば大したことありません。
（というかそれが許容できなければもうこのデータは使えません...）


### 「一町域が二以上の郵便番号で表される場合」

|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|0600042|ﾎｯｶｲﾄﾞｳ|ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ|ｵｵﾄﾞｵﾘﾆｼ(1-19ﾁｮｳﾒ)|北海道|札幌市中央区|大通西（１～１９丁目）|
|0640820|ﾎｯｶｲﾄﾞｳ|ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ|ｵｵﾄﾞｵﾘﾆｼ(20-28ﾁｮｳﾒ)|北海道|札幌市中央区|大通西（２０～２８丁目）|

これは同じ町域で、複数の郵便番号にまたがるパターンです。
丁目が分断されてカッコ書きになっているものが多いです。
このパターンは郵便番号からの検索などではそのまま使っても害のない場合が多いかと思いますが、住所から逆引きする場合には注意が必要です。
可能であれば、「大通西１丁目」「大通西２丁目」...といったように分離したいところです。


### 「一つの郵便番号で二以上の町域を表す場合」
|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|0680546|ﾎｯｶｲﾄﾞｳ|ﾕｳﾊﾞﾘｼ|ﾅﾝﾌﾞｱｵﾊﾞﾁｮｳ|北海道|夕張市|南部青葉町|
|0680546|ﾎｯｶｲﾄﾞｳ|ﾕｳﾊﾞﾘｼ|ﾅﾝﾌﾞｷｸｽｲﾁｮｳ|北海道|夕張市|南部菊水町|

これは上記とは逆に、1つの郵便番号に複数の住所が存在します。
郵便番号からの検索の場合は、リスト表示などが必要になるパターンです。
ちなみに、市区町村どころか都道府県をまたがるレアケースも存在し、かつCSV上では続きレコードではなく全く別の場所に存在します。
都道府県単位での何かしらの処理をする場合は要注意です。

|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|4980000|ﾐｴｹﾝ|ｸﾜﾅｸﾞﾝｷｿｻｷﾁｮｳ|ｲｶﾆｹｲｻｲｶﾞﾅｲﾊﾞｱｲ|三重県|桑名郡木曽岬町|以下に掲載がない場合|
|4980000|ｱｲﾁｹﾝ|ﾔﾄﾐｼ|ｲｶﾆｹｲｻｲｶﾞﾅｲﾊﾞｱｲ|愛知県|弥富市|以下に掲載がない場合|


### 「小字毎に番地が起番されている町域」
|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|9591361|ﾆｲｶﾞﾀｹﾝ|ｶﾓｼ|ｹﾞｼﾞｮｳ|新潟県|加茂市|下条|

これは日本郵便のサイトにも例が書いてありますが、郵便番号と番地だけでは住所が特定できないパターンです。
上記の住所は実際には、

* 新潟県加茂市下条戊617
* 新潟県加茂市下条乙617

といった住所があり、郵便番号（959-1361）と番地（617）だけでは住所が特定できないということです。
ただしこれは郵便番号データとしては特に気にする必要がない（CSV上は小字以降に何があるのかは分かりようがない）ので特に処理不要なことが多いかと思われます。
（「字（アザ）がある場合は必ず記載ください」などのアラートが出ると親切かもですね。見たことないですが。）


### 「町域部分の文字数が38文字（またはフリガナ部分の文字数が76文字）を越える場合」
|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|0660005|ﾎｯｶｲﾄﾞｳ|ﾁﾄｾｼ|ｷｮｳﾜ(88-2､271-10､343-2､404-1､427-|北海道|千歳市|協和（８８－２、２７１－１０、３４３－２、４０４－１、４２７－|
|0660005|ﾎｯｶｲﾄﾞｳ|ﾁﾄｾｼ|3､431-12､443-6､608-2､641-8､814､842-|北海道|千歳市|３、４３１－１２、４４３－６、６０８－２、６４１－８、８１４、８４２－|
|0660005|ﾎｯｶｲﾄﾞｳ|ﾁﾄｾｼ|5､1137-3､1392､1657､1752ﾊﾞﾝﾁ)|北海道|千歳市|５、１１３７－３、１３９２、１６５７、１７５２番地）|

郵便番号データで一番やっかいなのがこれです。
管理しているシステムの仕様なのか、この時代においても何らかの理由により76バイトしか入らないようです。
上記は同じ郵便番号の住所ですが、3行にわたって記載されています。この場合は（カッコ）の中に番地があるので「、」で分離すればいいのかなーと考えますが、下記はいかがでしょうか。

|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|9218046|ｲｼｶﾜｹﾝ|ｶﾅｻﾞﾜｼ|ｵｵｸﾜﾏﾁ(ｱ､ｲ､ｲ､ｳ､ｳｴﾉ､ｵ､ｵｵﾂ､ｶﾈﾂｷﾔﾏ､ｶﾐｶﾜﾗ､ｶﾐﾈｺｼﾀ､|石川県|金沢市|大桑町（ア、イ、ヰ、ウ、上野、ヲ、オ乙、鐘搗山、上川原、上猫下、|
|9218046|ｲｼｶﾜｹﾝ|ｶﾅｻﾞﾜｼ|ｸ､ｹ､ｺﾞｼｮｶﾞﾀﾞﾆ､ｺﾃﾞﾗﾔﾏ､ｼ､ｼﾓｳｴﾉ､ｼﾓﾆｼｶﾞｹ､ﾀﾞｲﾗ､ﾁ､ﾂｵﾂ､ﾂﾍｲ､ﾃ､ﾄ､|石川県|金沢市|ク、ケ、御所谷、小寺山、シ、下上野、下西欠、平、チ、ツ乙、ツ丙、テ、ト、|
|9218046|ｲｼｶﾜｹﾝ|ｶﾅｻﾞﾜｼ|ﾅｶｳｴﾉ､ﾅｶｵﾔﾏ､ﾅｶﾀﾞｲﾗ､ﾅｶﾉｵｵﾋﾗ､ﾆｼﾉﾔﾏ､ﾈｺﾉｼﾀｲ､ﾉ､ﾊ､ﾋﾗｷ､|石川県|金沢市|中上野、中尾山、中平、中ノ大平、西ノ山、猫シタイ、ノ、ハ、開、|
|9218046|ｲｼｶﾜｹﾝ|ｶﾅｻﾞﾜｼ|ﾎｳｼﾔﾏ､ﾎﾞｳﾔﾏ､ﾏ､ﾏｽｶﾜﾌﾞﾁ､ﾑ､ﾓﾄｽｴ､ﾓﾄﾜｸﾅﾐｺｳ､ﾔ､ﾘ､ﾙ､ﾚｵﾂ､|石川県|金沢市|法師山、坊山、マ、鱒川淵、ム、元末、元涌波庚、ヤ、リ、ル、レ乙、|
|9218046|ｲｼｶﾜｹﾝ|ｶﾅｻﾞﾜｼ|ﾚｺｳ､ﾛｵﾂ､ﾛｺｳ､ﾜ)|石川県|金沢市|レ甲、ロ乙、ロ甲、和）|

|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|6511102|ﾋｮｳｺﾞｹﾝ|ｺｳﾍﾞｼｷﾀｸ|ﾔﾏﾀﾞﾁｮｳｼﾓﾀﾆｶﾞﾐ(ｵｵｶﾐﾀﾞﾆ､ｼｭｳﾎｳｶﾞﾊﾗ､ﾅｶｲﾁﾘﾔﾏ<9ﾊﾞﾝﾁﾉ4､12ﾊﾞﾝﾁｦﾉｿﾞｸ>､|兵庫県|神戸市北区|山田町下谷上（大上谷、修法ケ原、中一里山「９番地の４、１２番地を除く」、|
|6511102|ﾋｮｳｺﾞｹﾝ|ｺｳﾍﾞｼｷﾀｸ|ﾅｶﾞｵﾔﾏ､ﾌﾀﾀﾋﾞｺｳｴﾝ)|兵庫県|神戸市北区|長尾山、再度公園）|

|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|4280049|ｼｽﾞｵｶｹﾝ|ｼﾏﾀﾞｼ|ﾏｷﾉﾊﾗ(250-343ﾊﾞﾝﾁ<255､256､258､259､262､|静岡県|島田市|牧之原（２５０～３４３番地「２５５、２５６、２５８、２５９、２６２、|
|4280049|ｼｽﾞｵｶｹﾝ|ｼﾏﾀﾞｼ|276､294-300､302-304ﾊﾞﾝﾁｦﾉｿﾞｸ>)|静岡県|島田市|２７６、２９４～３００、３０２～３０４番地を除く」）|

|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|9960301|ﾔﾏｶﾞﾀｹﾝ|ﾓｶﾞﾐｸﾞﾝｵｵｸﾗﾑﾗ|ﾐﾅﾐﾔﾏ(430ﾊﾞﾝﾁｲｼﾞｮｳ<1770-1-2､1862-42､|山形県|最上郡大蔵村|南山（４３０番地以上「１７７０－１～２、１８６２－４２、|
|9960301|ﾔﾏｶﾞﾀｹﾝ|ﾓｶﾞﾐｸﾞﾝｵｵｸﾗﾑﾗ|1923-5ｦﾉｿﾞｸ>､ｵｵﾔﾁ､ｵﾘﾜﾀﾘ､ｶﾝｶﾈﾉ､ｷﾝｻﾞﾝ､ﾀｷﾉｻﾜ､ﾄﾖﾏｷ､ﾇﾏﾉﾀﾞｲ､|山形県|最上郡大蔵村|１９２３－５を除く」、大谷地、折渡、鍵金野、金山、滝ノ沢、豊牧、沼の台、|
|9960301|ﾔﾏｶﾞﾀｹﾝ|ﾓｶﾞﾐｸﾞﾝｵｵｸﾗﾑﾗ|ﾋｼﾞｵﾘ､ﾋﾗﾊﾞﾔｼ)|山形県|最上郡大蔵村|肘折、平林）|

|郵便番号|都道府県名（カナ）|市区町村名（カナ）|町域名（カナ）|都道府県名|市区町村名|町域名|
|---|---|---|---|---|---|---|
|0482402|ﾎｯｶｲﾄﾞｳ|ﾖｲﾁｸﾞﾝﾆｷﾁｮｳ|ｵｵｴ(1ﾁｮｳﾒ､2ﾁｮｳﾒ<651､662､668ﾊﾞﾝﾁ>ｲｶﾞｲ､3ﾁｮｳﾒ5､1|北海道|余市郡仁木町|大江（１丁目、２丁目「６５１、６６２、６６８番地」以外、３丁目５、１|
|0482402|ﾎｯｶｲﾄﾞｳ|ﾖｲﾁｸﾞﾝﾆｷﾁｮｳ|3-4､20､678､687ﾊﾞﾝﾁ)|北海道|余市郡仁木町|３－４、２０、６７８、６８７番地）|

いかがでしょうか。正確な住所を出せる自信ありますか？私はそのまま連結する以外やりたくないです（笑）
かつ、この複数行にまたがるパターンについては、フラグがありません。つまり複数行にまたがっているかどうかの判定は、なんと自分で行う必要があります！

### そのほか
町域に「以下に掲載がない場合」「の次に番地がくる場合」「一円」等々といった、本来住所ではない~~無駄な~~温かみのある説明書きが入っていたりしますので、住所データとして使う場合は取り除く必要があります。
また、頻出するのが「（その他）」記載。連続したデータを見れば意味が分かりますが、ピンポイントでこの住所だけ表示すると意味不明な表記となってしまいます。


# 皆さんお困りですよね

長々と書いてしまいましたが、世の中の皆さんもやはり困ってらっしゃるようで、色々な先人達がこのデータを何とか綺麗にしたものやツールを有料無料問わず公開されていますので、そちらを使われるのが一番良いかと思います。（丸投げ）

私はちょっと違った方向から、このデータを愛でるためのツールを作りました。
単純に、上記のような「要注意データ」をピックアップして表示するだけ、というなんとも使い道のなさそうなやつです。自分の作った住所検索や拾ってきたツールがちゃんと整形できているかのテストなどに使える...？かどうかは分かりませんが、下記に置いてあります。
https://github.com/yukihato/ken-all-sampling/

単純に下記の住所を抽出してランダムでそれぞれ1つずつ表示します。

* type1:一町域が二以上の郵便番号で表される場合
* type2:一つの郵便番号で二以上の町域を表す場合
* type3:町域部分の文字数が38文字を越える場合
* type4:町域に想定しない記号が入っている
* type5:その他系

```
$ node index.js type4
{
  type4: [
    {
      x0401: '23221',
      oldPostcode: '44113',
      postcode: '4411336',
      prefKana: 'ｱｲﾁｹﾝ',
      cityKana: 'ｼﾝｼﾛｼ',
      townKana: 'ﾄﾐｵｶ(ﾔｼｷﾁｸ)',
      pref: '愛知県',
      city: '新城市',
      town: '富岡（○○屋敷）',
      flag1: '1',
      flag2: '0',
      flag3: '0',
      flag4: '0',
      flag5: '0',
      flag6: '0',
      multiple: 1
    }
  ]
}
```


しかし、○○屋敷ってなんでしょうね...富豪がいっぱい住んでるんでしょうか。