[Python] 郵便番号から住所を取得する②

はじめに

お疲れさまです🍵

今回は、前回の記事の続きで、郵便局のデータを取得・活用するスクリプトを作成していきます。

よろしくお願いいたします!

[Python] 郵便番号から住所を取得する①
はじめにこんにちは!今日はPythonで郵便番号から住所を取得できるログラムを作っていきたいと思います。環境は下記の通りです。開発環境言語:Python(Ubuntu環境で実行)データベース:MySQL(Ubuntu環境で稼働)OS:mac…

郵便番号から住所を取得する

以下のコードでは、MySQLに保存された郵便局データベースを使って、7桁の郵便番号から対応する住所を取得します。

import mysql.connector

def get_address_by_zip(zip_code):
# 郵便番号の形式チェック
if len(zip_code) != 7 or not zip_code.isdigit():
return "郵便番号は7桁の数字で入力してください。"

try:
# データベースに接続
conn = mysql.connector.connect(
host='***', #データベースが動いているサーバーのアドレス
user='***', #ログインユーザー名
password='***', #ユーザー名に対応するパスワード
database='***
*, #接続するデータベース名
connection_timeout=5 #5秒以内に接続できなければタイムアウトとしてエラーを吐く
)
cursor = conn.cursor()

# 郵便番号に一致する住所を検索
query = """
SELECT kana1, kana2, kana3, name1, name2, name3
FROM post
WHERE post_code = %s
"""
cursor.execute(query, (zip_code,))
results = cursor.fetchall()

if results:
# かな・漢字の住所を結合して表示
kana = " ".join([part if part is not None else "" for part in results[0][:3]])
name = " ".join([part if part is not None else "" for part in results[0][3:]])
return f"住所(かな): {kana.strip()}\n住所(漢字): {name.strip()}"
else:
return "該当する住所が見つかりませんでした。"

except mysql.connector.Error as err:
return f"データベースエラー: {err}"

finally:
# リソースの後始末
if 'cursor' in locals():
cursor.close()
if 'conn' in locals():
conn.close()

# ユーザーから郵便番号を受け取って検索
zip_code = input("郵便番号(7桁)を入力してください: ").strip()
address = get_address_by_zip(zip_code)
print(address)

関数の説明

この関数では、ユーザーが入力した郵便番号をもとに、対応する住所をデータベースから取得しています。

まず最初に、入力された郵便番号の形式をチェックします。

len(zip_code) != 7

は、郵便番号が7文字じゃない場合はアウトです。

日本の郵便番号は7桁なので、このチェックが必要になります。

not zip_code.isdigit()

ここでは、郵便番号に数字以外の文字が含まれていた場合もエラーにします。

(例)「160-0011」や「abc1234」など

続いて、データベースとMYSQLを接続します。

mysql.connector.connect()

でPython からデータベースへ接続しています。

接続エラーをハンドリングするため、try-catchのブロック内に書いています。

この接続がうまくいけば、次の処理でデータベースから郵便番号を使って、住所データを検索することができます。

逆に、サーバーが落ちていたり、パスワードが間違っていたりすると、この時点でエラーになります。

次に、カーソルを作成します。

cursor = conn.cursor()

カーソルは、プログラムとデータベースと間でやりとりを行うためのものです。

今回の場合は、クエリを実行したり、実行結果を受け取ったりします。

ここでは、郵便番号に一致する住所を検索するSQLが書かれています。

# 郵便番号に一致する住所を検索
query = """
SELECT kana1, kana2, kana3, name1, name2, name3
FROM post
WHERE post_code = %s
"""

MySQLに送るSELECT文を準備しています。

クエリ文は、今回は分かりやすさを優先してコード内にハードコーディングしています。

(本格的なアプリ開発では、設定ファイルや別管理にすることが多い点だけ少し注意です!)

カラムの意味は、都道府県/市区町村/町名です。

kana1, kana2, kana3 は住所のかな表記、

name1, name2, name3 は住所の漢字表記になってます。

WHERE post_code = %s


は、検索条件です。

post_code(郵便番号)が指定された値(後で渡す値)と一致するデータだけを取得します。

%s

はプレースホルダーです。

悪意のあるデータによる攻撃を防ぐために、値を後から別で渡し、クエリと値を分けて実行します。

続いて、クエリ実行と結果の取得します。

cursor.execute(query, (zip_code,))

queryに書いたSQL文をDBに送って実行します。

(zip_code,)%s に当てはめる値。タプルで渡す必要があるのでカンマ付きにしています。

※タプル(tuple)とはデータ型のひとつで、複数の値をまとめて持てます。

results = cursor.fetchall()

検索結果が複数行あったときのために、全部まとめて取り出しています。

resultsはリスト形式で、中身はタプルの集まりです。

たとえばこんな感じになります。

[('トウキョウト', 'シンジュクク', 'シンジュク', '東京都', '新宿区', '新宿')]

郵便番号で住所を取り出したときのこの行:

('トウキョウト', 'シンジュクク', 'シンジュク', '東京都', '新宿区', '新宿')

1行分の住所データが1つのタプルにまとめられてます。

if results:
# かな・漢字の住所を結合して表示
kana = " ".join([part if part is not None else "" for part in results[0][:3]])
name = " ".join([part if part is not None else "" for part in results[0][3:]])
return f"住所(かな): {kana.strip()}\n住所(漢字): {name.strip()}"
else:
return "該当する住所が見つかりませんでした。"

ここでは、DBから取得した検索結果を整えて返します。

条件文では、検索結果が「存在するかどうか」をチェックします。

results[0] には、以下のような値が入っているとします:

('トウキョウト', 'シンジュクク', 'シンジュク', '東京都', '新宿区', '新宿')

これをそれぞれ、かなの住所と漢字の住所に分けて整形します。

kana = " ".join([part if part is not None else "" for part in results[0][:3]])
name = " ".join([part if part is not None else "" for part in results[0][3:]])

[:3] で最初の3つ(かな)を、[3:] で後ろの3つ(漢字)を取り出しています。

None の場合は空文字 "" に置き換えて、エラーにならないようにしています。

" ".join(...) で、それらのパーツをスペースでつなげています。

return f"住所(かな): {kana.strip()}\n住所(漢字): {name.strip()}"

住所をひらがなと漢字でフォーマットして返します。

そして、次の部分:

else:
return "該当する住所が見つかりませんでした。"

もし該当する住所が見つからなかった場合に「該当する住所が見つかりませんでした。」というメッセージを返します。

except mysql.connector.Error as err:
return f"データベースエラー: {err}"

MySQLの接続中にエラーが発生した場合にエラーをキャッチし、そのエラーメッセージを返します。

return f"データベースエラー: {err}"

これにより、MySQLのエラーが発生した際に、エラーメッセージの内容が表示されます。

pythonコピーする編集するfinally:
# リソースの後始末
if 'cursor' in locals():
cursor.close()
if 'conn' in locals():
conn.close()

finallyブロックは、tryブロックとexceptブロックの後に必ず実行される部分で、

リソースの掃除や不要なデータの削除を行います。

cursor.close()

は、データベース操作を終了した後、カーソルを閉じます。

conn.close()

はデータベースの接続を閉じて、リソースを解放します。

if 'cursor' in locals()if 'conn' in locals()

は、それぞれカーソルデータベースが定義されている場合にのみ、閉じる処理を行います。

そうすることで、未定義の変数に対して、エラーが発生しないようにしています。

zip_code = input("郵便番号(7桁)を入力してください: ").strip()

は、ユーザーに郵便番号を入力してもらい、入力された内容を整えて、変数 zip_code に格納します。

input()はユーザーからの入力を受け取ります。

.strip() は文字列の先頭と末尾の余分な空白文字を取り除きます。

address = get_address_by_zip(zip_code)
print(address)

郵便番号に基づいて住所を取得します。

get_address_by_zip(zip_code)では、関数get_address_by_zip() を呼び出しています。

引数として、先ほど取得した郵便番号 zip_code を渡しています。

get_address_by_zip() が返す住所の結果は、変数 address に格納されます。

この後、print(address)で、変数addressに格納された住所を表示します。

まとめ

今回は、PythonとMySQLを使って、郵便番号から住所を検索しました。

ありがとうございました!

コメント

タイトルとURLをコピーしました