Python一覧

Python の正規表現で電話番号を抽出する

Python の正規表現で電話番号を抽出します。

正規表現って難しいですよね。難しい記号だらけで訳がわかりません。しかし、その難しさに比例し、機能としては強力なものになっています。

Python の正規表現 re モジュール

import re

まず、Python で正規表現を使うには re モジュールをインポートします。この re モジュールに、正規表現関連すべての関数が入っています。

正規表現オブジェクトを生成 compile()

phone_regex = re.compile(r'''(
    (\d{2,4}|\(\d{2,4}\))  # 市外局番
    (\s|-)                 # 区切りは空白もしくはハイフン
    (\d{3,4})              # 市内局番
    (\s|-)                 # 区切りは空白もしくはハイフン
    (\d{4})                # 加入者番号
    )''', re.VERBOSE)

次に正規表現オブジェクトを生成します。電話番号を抽出する正規表現オブジェクトを生成しています。詳細については、以下の通りです。

(\d{2,4}|\(\d{2,4}\))

市外局番は、2〜4桁の数字(\d)または括弧で囲われた2〜4桁の数字でマッチするようにしています。

今回、市外局番は必須としていますが、任意にしたい場合は、? を最後に追加すれば良いでしょう。

(\s|-)

区切り文字は、空白(\s)またはハイフンでマッチするようにしています。

こちらも任意にしたい場合は、最後に ? を追加すれば良いでしょう。

re.VERBOSE

正規表現内にコメントを書けるようにするためのオプションです。

マッチする最初の場所を探す search()

# 区切り文字がないので、マッチしない
test1 = '0123456789'
m = phone_regex.search(test1)
print('test1:', m)  # test1: None

# マッチする
test2 = '012-345-6789'
m = phone_regex.search(test2)
print('test2:', m)  # test2: <_sre.SRE_Match object; span=(0, 12), match='012-345-6789'>

# マッチするのは、最初の1つ
test3 = '012-345-6789 987 654 3210'
m = phone_regex.search(test3)
print('test3:', m)  # test3: <_sre.SRE_Match object; span=(0, 12), match='012-345-6789'>

compile 関数で生成したオブジェクトをもとに、search 関数で電話番号を抽出します。

search 関数は、マッチする最初の場所を探す関数です。マッチしない場合は、None を返します。

マッチする最初の場所を探すので、マッチ対象が複数あったとしても、最初の一つしか抽出しません。

マッチするすべてを探す findall()

# 全てマッチする
test4 = test3
l = phone_regex.findall(test4)
print('test4:', l)  # test4: [('012-345-6789', '012', '-', '345', '-', '6789'), ('987 654 3210', '987', ' ', '654', ' ', '3210')]

search 関数は最初の一つしか抽出しませんが、findall 関数は、マッチした全てを抽出できます。search を使うか、findall を使うかは、その時々によって使い分けましょう。

Python の正規表現で電話番号を抽出

import re

phone_regex = re.compile(r'''(
    (\d{2,4}|\(\d{2,4}\))  # 市外局番
    (\s|-)                 # 区切りは空白もしくはハイフン
    (\d{3,4})              # 市内局番
    (\s|-)                 # 区切りは空白もしくはハイフン
    (\d{4})              # 加入者番号
    )''', re.VERBOSE)

# 区切り文字がないので、マッチしない
test1 = '0123456789'
m = phone_regex.search(test1)
print('test1:', m)  # test1: None

# マッチする
test2 = '012-345-6789'
m = phone_regex.search(test2)
print('test2:', m)  # test2: <_sre.SRE_Match object; span=(0, 12), match='012-345-6789'>

# マッチするのは、最初の1つ
test3 = '012-345-6789 987 654 3210'
m = phone_regex.search(test3)
print('test3:', m)  # test3: <_sre.SRE_Match object; span=(0, 12), match='012-345-6789'>

# 全てマッチする
test4 = test3
l = phone_regex.findall(test4)
print('test4:', l)  # test4: [('012-345-6789', '012', '-', '345', '-', '6789'), ('987 654 3210', '987', ' ', '654', ' ', '3210')]

上記で説明した内容を合体し、main.py というファイルに保存しました。

この main.py を実行すると、以下のような結果になります。

$ python main.py
test1: None
test2: <_sre.SRE_Match object; span=(0, 12), match='012-345-6789'>
test3: <_sre.SRE_Match object; span=(0, 12), match='012-345-6789'>
test4: [('012-345-6789', '012', '-', '345', '-', '6789'), ('987 654 3210', '987', ' ', '654', ' ', '3210')]
$

まとめ

Python の正規表現で電話番号を抽出しました。

正規表現は、入力フォームのバリデーションルールだったり、ログを解析するときだったりと、様々なシーンで使用します。

ある人は、「正規表現を知っているのは、問題を解くのに3,000ステップもかかっていたものが、3ステップで済むくらいの違いがある」と言っているほど強力な機能です。

是非ともマスターしたいスキルですね。