郵便番号から住所を自動入力する

郵便番号検索のデータを入手

郵便番号と住所の参照データは郵便局のサイトからダウンロードできます。全国一括(1,735,542Byte)をダウンロードします。
http://www.post.japanpost.jp/zipcode/dl/kogaki.html
csvでダウンロードできるのでそのまま使うなりMySQLに入れちゃうなりいろいろできます。が、Shift JISのCR+LFで書かれている(エクセルではそのまま開けますね。)ので取り急ぎUTF-8に文字コード変換しておく。

データの内容は以下のようになっています。
01101,"060 ","0600000","ホッカイドウ","サッポロシチュウオウク","イカニケイサイガナイバアイ","北海道","札幌市中央区","以下に掲載がない場合",0,0,0,0,0,0という風に15個のデータが1つのレコードになっているようです。MySQLに入れるならこの構造でそのままインポートしてしまえばいいです。csvを直接使うのでも十分できるはできる量ではあるかと。csvの扱いについてはPHP4だと確かテキストで読まないとだめだったような気がしますのでご注意。

  • 01101:市町村番号みたいなの(我々は関係ないです)
  • 060:3桁
  • 0600000:3桁+4桁
  • ホッカイドウ:都道府県(半角カタカナ)
  • サッポロシチュウオウク:市町村区(半角カタカナ)
  • アサヒガオカ:町名(半角カタカナ)
  • 北海道:都道府県(漢字)
  • 札幌市中央区:市町村区(漢字)
  • 旭ケ丘:町名(漢字)
  • 0:不明なフラグ
  • 0:不明なフラグ
  • 0:不明なフラグ
  • 0:不明なフラグ
  • 0:不明なフラグ
  • 0:不明なフラグ

<form action="" method="post">
<input type="text" size="3" name="fmt3" />-<input type="text" size="4" name="fmt4" />
<input type="submit" value="検索" name="submit"/>
</form>

<?php
# 入力された郵便番号
if ($_POST) {
$search_number3 = $_POST['fmt3'];
$search_number4 = $_POST['fmt4'];

$search_number3 = mb_convert_kana($search_number3,"n","UTF-8");
$search_number4 = mb_convert_kana($search_number4,"n","UTF-8");

#-------------------
# 入力数値のサニタイズ
#-------------------
$search_number3 = htmlentities($search_number3, ENT_QUOTES);
$search_number4 = htmlentities($search_number4, ENT_QUOTES);

$search_number3 = substr($search_number3, 0, 3);
$search_number4 = substr($search_number4, 0, 4);

# 3桁 4桁以外
if (!preg_match("/^¥d{3}/",$search_number3) ¦¦ !preg_match("/^¥d{4}/",$search_number4)) {
# 0 Format
$search_number3 = sprintf('%03d', $search_number3);
$search_number4 = sprintf('%04d', $search_number4);
}

# 整形
$search_number7 = $search_number3.$search_number4;

# Debug print
print "<h1>$search_number3 - $search_number4</h1>";
//print "search: $search_number7<br />";

#------------
# CSV読み込み
#------------

$fileName = './KEN_ALL_utf8.csv';
$file = fopen($fileName,"r");

$i=0;
$match_flg = 0;

if (is_file($fileName)) {
while(!feof($file)){

$str = fgetcsv($file);
list($prefecturesNumber,$number3,$number7,$prefectures_katakana,$city_katakana,$adress_katakana,$prefectures_name,$city_name,$adress_name) = $str;

# 不要な情報を削除
$number3 = trim($number3);
$number7 = trim($number7);
$adress_name = mb_ereg_replace("(次のビルを除く)",'',$adress_name );
$adress_name = mb_ereg_replace('(地階・階層不明)','',$adress_name );
$adress_name = mb_ereg_replace('以下に掲載がない場合','',$adress_name );

if ($search_number7 == $number7/* ¦¦ $search_number3 == $number3*/) {

print "$prefectures_name $city_name $adress_name"."¥n";
//print "$number7";
$match_flg = 1;
break;
}
$i++;
}
fclose($file);

if ($match_flg == 0) {
print "";
}
}
}

?>
Sampleはこちら

Ajaxを使ってリアルタイム検索をする

郵便番号から住所を自動的に補完するフォームなんかでよく使っているんですが、phpと併用してAjaxでもって(ほぼ)リアルタイムでページ遷移なしで検索が可能です。今回は$.postでもってJSとPHPを通信させます。流としてはFormからsubmitする代わりにjQueryでinputの値を取り出してAjaxでもってPHPファイルに送信し、結果をjQUeryに再び戻してもらうという流れになります。PHPでPOSTデータを受け取る際には、そのまま$_POSTで受けます。 PHPでの処理結果(検索結果)は再びjQueryに戻すわけですが、特に変数に渡すとかいうのではなく単純にPHPでもってechoやprint(普通に出力)という感じになります。HTMLも含めてphpから返ってくる値をjQueryは全部拾うのでHTMLヘッダーとかmetaデータとかは必要ないです。Sample

HTMLフォーム部分
<form action="" method="post" id="SearchPost">
<input type="text" size="3" name="fmt3" id="fmt3" />-<input type="text" size="4" name="fmt4" id="fmt4" /><br />
Prefectures: <input Type="text" size="10" name="Prefectures" id="Prefectures" value=""/>
City: <input Type="text" size="10" name="City" id="City" value=""/>
Address: <input Type="text" size="10" name="Adress" id="Adress" value=""/>
<input type="submit" value="検索" name="submit" id="SearchPostSubmit"/>
</form>

jQuery部分
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<script type="text/javascript">
$(function(){

function search_post_submit() {
var val_fmt3 = $("#fmt3").val();
var val_fmt4 = $("#fmt4").val();

$.post(
"./search_post_csv.php",
{'fmt3':val_fmt3, 'fmt4':val_fmt4,},
function(data){
var postnumber = new Array();
var postnumber = data.split('&nbsp;');
$("#Prefectures").val(postnumber[0]);
$("#City").val(postnumber[1]);
$("#Adress").val(postnumber[2]);
}
);
}

$("form#SearchPost").submit(function(){
search_post_submit();
return false;
});
});
</script>

PHP部分
<?php
if ($_POST) {
$search_number3 = $_POST['fmt3'];
$search_number4 = $_POST['fmt4'];

$search_number3 = mb_convert_kana($search_number3,"n","UTF-8");
$search_number4 = mb_convert_kana($search_number4,"n","UTF-8");

#-------------------
# 入力数値のサニタイズ
#-------------------
$search_number3 = htmlentities($search_number3, ENT_QUOTES);
$search_number4 = htmlentities($search_number4, ENT_QUOTES);

$search_number3 = substr($search_number3, 0, 3);
$search_number4 = substr($search_number4, 0, 4);

# 3桁 4桁以外
if (!preg_match("/^¥d{3}/",$search_number3) ¦¦ !preg_match("/^¥d{4}/",$search_number4)) {
# 0 Format
$search_number3 = sprintf('%03d', $search_number3);
$search_number4 = sprintf('%04d', $search_number4);
}

# 整形
$search_number7 = $search_number3.$search_number4;

# Debug print
//print "<h1>$search_number3 - $search_number4</h1>";
//print "search: $search_number7<br />";

#------------
# CSV読み込み
#------------

$fileName = './KEN_ALL_utf8.csv';
$file = fopen($fileName,"r");

$i=0;
$match_flg = 0;

if (is_file($fileName)) {
while(!feof($file)){

$str = fgetcsv($file);
list($prefecturesNumber,$number3,$number7,$prefectures_katakana,$city_katakana,$adress_katakana,$prefectures_name,$city_name,$adress_name) = $str;

# 不要な情報を削除
$number3 = trim($number3);
$number7 = trim($number7);
$adress_name = mb_ereg_replace("(次のビルを除く)",'',$adress_name );
$adress_name = mb_ereg_replace('(地階・階層不明)','',$adress_name );
$adress_name = mb_ereg_replace('以下に掲載がない場合','',$adress_name );

if ($search_number7 == $number7/* ¦¦ $search_number3 == $number3*/) {

print $prefectures_name.'&nbsp;'.$city_name.'&nbsp;'.$adress_name;
//print "$number7";
$match_flg = 1;
break;
}
$i++;
}
fclose($file);

if ($match_flg == 0) {
print "";
}
}
}
?>

特にここで書く必要もないのですが$.ajax,$.post,$.get関係のリモート間通信は、Basic認証などがかかっていると通りません。開発環境などで動作させる時は動かないということがままあるのでご注意。