http://www.post.japanpost.jp/zipcode/download.html
これを使って、〒番号から住所を得る PHP プログラムを作ってみた。
エンコーディングは、UTF-8。
インデックスの作成などをしていないため処理は遅いが、ダウンロードした CSV をそのまま利用できるのでメンテナンスは楽だ。
CSV ファイルは、上記サイトの、「住所の郵便番号のダウンロード」(どちらでもよい) と「事業所の個別郵便番号のダウンロード」から LZH ファイルをダウンロードし、解凍しておく。
<?php$flg_error = FALSE;$result = FALSE;// フォーマットタイプ$format = '';if (array_key_exists('t', $_REQUEST)) { $format = $_REQUEST['t']; if ($format != 's' && $format != 'x' && $format != 'j') { $format = ''; }}if ($format == '') { $format = 's';}// 郵便番号$zip_code = '';if (array_key_exists('z', $_REQUEST)) { $zip_code = $_REQUEST['z']; if (!preg_match('/^\d{7}$/', $zip_code)) { $zip_code = ''; }}if ($zip_code == '') { $flg_error = TRUE;}if (!$flg_error) { // データファイル define('DATA_DIR', '../../data/yubin_code'); $fh = fopen(DATA_DIR . '/ken_all.csv', 'r'); if ($fh === FALSE) { exit; } while (($data = fgetcsv($fh, 1000)) !== FALSE) { if ($data[2] == $zip_code) { // エンコーディングを変換 $data[3] = mb_convert_encoding($data[3], 'UTF-8', 'Shift_JIS'); $data[4] = mb_convert_encoding($data[4], 'UTF-8', 'Shift_JIS'); $data[5] = mb_convert_encoding($data[5], 'UTF-8', 'Shift_JIS'); $data[6] = mb_convert_encoding($data[6], 'UTF-8', 'Shift_JIS'); $data[7] = mb_convert_encoding($data[7], 'UTF-8', 'Shift_JIS'); $data[8] = mb_convert_encoding($data[8], 'UTF-8', 'Shift_JIS'); // $data[9] が 1 の場合は、$data[5], $data[8] の末尾の (...) を取 // る。 // (...) が存在しない場合は、$data[5], $data[8] を空文字列とする。 if ($data[9] == 1) { if (preg_match('/\(.+\)$/', $data[5])) { $data[5] = preg_replace('/\s*\(.+\)$/', '', $data[5]); } else { $data[5] = ''; } if (preg_match('/(.+)$/', $data[8])) { $data[8] = preg_replace('/\s*(.+)$/', '', $data[8]); } else { $data[8] = ''; } } // $data[12] が 1 の場合は、$data[5], $data[8] を空文字列とする。 if ($data[12] == 1) { $data[5] = $data[8] = ''; } // $data[8] == '以下に掲載がない場合' の場合、$data[5], $data[8] // を空文字列とする if ($data[8] == '以下に掲載がない場合') { $data[5] = $data[8] = ''; } $result = array($data[0], // 全国地方公共団体コード $data[1], // (旧)郵便番号(5桁) $data[2], // 郵便番号(7桁) $data[3], // 都道府県名 (カタカナ) $data[4], // 市区町村名 (カタカナ) $data[5], // 町域名 (カタカナ) '', // 丁目、番地、建物名 (カタカナ) '', // 事業所名 (カタカナ) $data[6], // 都道府県名 $data[7], // 市区町村名 $data[8], // 町域名 '', // 丁目、番地、建物名 '', // 事業所名 '', // 取扱郵便局名 $data[9], // 一町域が二つ以上の郵便番号に分割 $data[10], // 小字毎に番地が起番されている $data[11], // 丁目を有する町域 $data[12], // 一つの郵便番号で二つ以上の町域表す '', // 個別番号の種別の表示 '', // 複数番号の有無 $data[13], // 更新フラグ $data[14], // 更新理由 ); break; } } fclose($fh); if ($result === FALSE) { // 見つからなかった場合は、事業所のリストを探す $fh = fopen(DATA_DIR . '/jigyosyo.csv', 'r'); if ($fh === FALSE) { return FALSE; } while (($data = fgetcsv($fh, 1000)) !== FALSE) { if ($data[7] == $zip_code) { // エンコーディングを変換 $data[1] = mb_convert_encoding($data[1], 'UTF-8', 'Shift_JIS'); $data[2] = mb_convert_encoding($data[2], 'UTF-8', 'Shift_JIS'); $data[3] = mb_convert_encoding($data[3], 'UTF-8', 'Shift_JIS'); $data[4] = mb_convert_encoding($data[4], 'UTF-8', 'Shift_JIS'); $data[5] = mb_convert_encoding($data[5], 'UTF-8', 'Shift_JIS'); $data[6] = mb_convert_encoding($data[6], 'UTF-8', 'Shift_JIS'); $data[9] = mb_convert_encoding($data[9], 'UTF-8', 'Shift_JIS'); $result = array($data[0], // 全国地方公共団体コード $data[8], // (旧)郵便番号(5桁) $data[7], // 郵便番号(7桁) '', // 都道府県名 (カタカナ) '', // 市区町村名 (カタカナ) '', // 町域名 (カタカナ) '', // 小字名、丁目、番地など (カタカナ) $data[1], // 事業所名 (カタカナ) $data[3], // 都道府県名 $data[4], // 市区町村名 $data[5], // 町域名 $data[6], // 小字名、丁目、番地など $data[2], // 事業所名 $data[9], // 取扱郵便局名 '', // 一町域が二つ以上の郵便番号に分割 '', // 小字毎に番地が起番されている '', // 丁目を有する町域 '', // 一つの郵便番号で二つ以上の町域表す $data[10], // 個別番号の種別の表示 $data[11], // 複数番号の有無 $data[12], // 更新フラグ '', // 更新理由 ); break; } } }}// シリアル化した文字列if ($format == 's') { header('Content-Type: text/plain;charset=Shift_JIS'); print(serialize($result));}// XML 形式elseif ($format == 'x') { header('Content-Type: text/xml'); print(data2Xml($result));}// JSON 形式else { if (function_exists('json_encode')) { header('Content-Type: text/x-json'); print(json_encode($result)); } else { // 未対応 header('Content-Type: text/plain'); print('Not supported'); }}/* * 郵便CSV配列をXMLに変換する */function data2Xml($data){ if (!is_array($data)) { return FALSE; } $xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'; $xml .= '<yubin>'; $xml .= '<data>'; // 全国地方公共団体コード(JIS X0401、X0402) $xml .= "<local_gov_code>{$data[0]}</local_gov_code>"; // (旧)郵便番号(5桁) $xml .= "<postal_code_old>{$data[1]}</postal_code_old>"; // 郵便番号(7桁) $xml .= "<postal_code>{$data[2]}</postal_code>"; // 都道府県名 (カタカナ) $xml .= "<pref_name_yomi>{$data[3]}</pref_name_yomi>"; // 市区町村名 (カタカナ) $xml .= "<city_name_yomi>{$data[4]}</city_name_yomi>"; // 町域名 (カタカナ) $xml .= "<town_name_yomi>{$data[5]}</town_name_yomi>"; // 小字名、丁目、番地など (カタカナ) $xml .= "<street_name_yomi>{$data[6]}</street_name_yomi>"; // 事業所名 (カタカナ) $xml .= "<org_name_yomi>{$data[7]}</org_name_yomi>"; // 都道府県名 $xml .= "<pref_name>{$data[8]}</pref_name>"; // 市区町村名 $xml .= "<city_name>{$data[9]}</city_name>"; // 町域名 $xml .= "<town_name>{$data[10]}</town_name>"; // 小字名、丁目、番地など $xml .= "<street_name>{$data[11]}</street_name>"; // 事業所名 $xml .= "<org_name>{$data[12]}</org_name>"; // 取扱郵便局名 $xml .= "<post_office_name>{$data[13]}</post_office_name>"; // フラグ $xml .= "<flag_1>{$data[14]}</flag_1>"; $xml .= "<flag_2>{$data[15]}</flag_2>"; $xml .= "<flag_3>{$data[16]}</flag_3>"; $xml .= "<flag_4>{$data[17]}</flag_4>"; $xml .= "<flag_5>{$data[18]}</flag_5>"; $xml .= "<flag_6>{$data[19]}</flag_6>"; $xml .= "<flag_7>{$data[20]}</flag_7>"; $xml .= "<flag_8>{$data[21]}</flag_8>"; $xml .= '</data>'; $xml .= '</yubin>'; return $xml;}?>コード中、
DATA_DIR の定義部分は、ken_all.csv と jigyosyo.csv の保存場所を指定しておく。これをたとえば、zip.php というファイル名でしかるべき場所に保存し、
http://HOSTNAME/PATH/zip.php?z=1120002として呼び出すと、郵便番号 112-0002 に該当する住所のデータが PHP でシリアル化された配列として表示される。
PHP から利用するには、
fopen などして呼び出し、unserialize すればよい。また、
http://HOSTNAME/PATH/zip.php?z=1120002&t=xとすると、XML 形式で、
http://HOSTNAME/PATH/zip.php?z=1120002&t=jとすると、JSON 形式で返される。
JSON 形式での出力には、モジュール php-json が必要である。
php-json は、PHP 5.2.0 からはデフォルトで組み込まれているようだ。
【変更履歴】
- 2007-09-09
- 事業所の個別郵便番号に対応。
- 出力フォーマットに XML 追加。
- 2007-10-02
- JSON 形式での出力に対応。


参考にさせていただきました。
このプログラムは使いやすいのですが、
ファイルを頭からなめている都合上、ちょっとだけ処理が遅いのがネックですよね。
色々と試してみた結果、
fgetcsv関数を使わずにfgets関数を使い、substrで分解して比較する
という形に修正したところ、処理速度が3倍くらいになりました。
よければお試しください。