人気ブログランキングへ

2007年08月06日

郵便番号から住所を調べる(PHP)

郵便局のホームページから、CSV 形式で郵便番号と住所の対照表がダウンロードできる。
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 形式での出力に対応。
posted by K/I at 20:45 | 東京 ☁ | Comment(1) | TrackBack(0) | 技術メモ | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
素晴らしいサンプルプログラムをありがとうございます。
参考にさせていただきました。

このプログラムは使いやすいのですが、
ファイルを頭からなめている都合上、ちょっとだけ処理が遅いのがネックですよね。
色々と試してみた結果、

fgetcsv関数を使わずにfgets関数を使い、substrで分解して比較する

という形に修正したところ、処理速度が3倍くらいになりました。
よければお試しください。
Posted by matsui at 2007年10月02日 19:34
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック