郵便番号を住所に(fetch版)

三重県の郵便番号を 5140001 のような形で入力し,住所を入力しようとすると,郵便番号からわかる住所の部分が自動的に入ります。

郵便番号:
住所:

ソース

このページのソースはブラウザから見ることができます。Ajaxにかかわるところは以下の部分です:

<script>
function doit() {
  const z = encodeURIComponent(document.getElementById("zip").value);
  fetch("lookup.php",
        { method: "POST",
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          body: "zip=" + z })
    .then(response => response.text())
    .then(data => document.getElementById("address").value = data);
}
</script>

フォームの部分は次のようになっています:

<form method="post">
<p>郵便番号:<input name="zip" id="zip" onchange="doit();"><br>
住所:<input name="address" id="address"><br>
<input type="submit" value="送信"></p>
</form>

サーバ側の処理を行う lookup.php は次のようになっています:

<?php
  header('Content-Type: text/html; charset=UTF-8');
  if ($_POST['zip']) {
    try {
      $db = new PDO('sqlite:yuubin.db');
      $st = $db->prepare("select address from yuubin where zip=? limit 1");
      $st->bindParam(1, $_POST['zip']);
      $st->execute();
      $a = $st->fetch();
      echo $a[0];
    } catch (PDOException $e) {
      echo "エラー";
    }
  }
?>

yuubin.dbはSQLiteのデータベースで,次のような形の表yuubinを含みます:

zipaddress
5140001三重県津市江戸橋
5140008三重県津市上浜町
…………

このような表を作る方法を以下に解説します。

解説

郵便番号データは日本郵便の郵便番号データダウンロードからダウンロードできます。何種類かありますが,どれを使ってもかまいません。以下の例では「読み仮名データの促音・拗音を小書きで表記するもの」を使いました。また,三重県のデータだけに限定しています。これは次のようなCSV形式になっています。三重県のデータだけでも2480件あります(2022年1月現在)。

24201,"514  ","5140000","ミエケン","ツシ","イカニケイサイガナイバアイ","三重県","津市","以下に掲載がない場合",0,0,0,0,0,0
24201,"514  ","5140017","ミエケン","ツシ","アイオイチョウ","三重県","津市","相生町",0,0,0,0,0,0
24201,"51411","5141139","ミエケン","ツシ","アオバダイ","三重県","津市","青葉台",0,0,1,0,0,0

3番目が7桁郵便番号,7〜9番目が住所です。これらだけをタブ区切りのUTF-8ファイルに書き出すには,Pythonなら次のようにします:

import pandas as pd

df = pd.read_csv("24MIE.CSV", header=None, encoding="cp932")
df2 = pd.DataFrame({"番号": df[2], "住所": df[6] + df[7] + df[8]})
df2.to_csv("24mie-utf8.tsv", index=False, header=False, sep="\t")

Rなら次のようにします:

x = read.csv("24MIE.CSV", header=FALSE, fileEncoding="CP932")
y = data.frame(x$V3, paste0(x$V7, x$V8, x$V9))
write.table(y, "24mie-utf8.tsv", quote=FALSE, sep="\t", row.names=FALSE,
            col.names=FALSE, fileEncoding="UTF-8")

これをデータベースに読み込ませるには,次のようにします:

sqlite3 yuubin.db
create table yuubin(zip text, address text);
.separator "\t"
.import 24mie-utf8.tsv yuubin
.quit

.separator "," とすればCSVも読めます(データ中にコンマがない場合)。

「以下に掲載がない場合」という文字列は省いておくほうがいいでしょう。どうやれば省けるか考えてください。

郵便番号CSVはいろいろややこしいところがあります。詳しくはこちらをご覧ください。

住所フォームについてはケンオールさんのこれだけは押さえよう!住所フォームの作り方が参考になります。