LoginSignup
12
9

More than 5 years have passed since last update.

pythonで電話番号を正規表現で

Posted at

スクレイピングしてきたraw_htmlから電話番号を抜き出すときの正規表現。いわゆる通常の000−000−0000というような3桁3桁4桁のハイフンありだけでなく、、、

  • 00-0000-0000
  • 0000-00-0000
  • 0120-000-000

更には、

  • (00)0000-0000
  • (0120)000000

のような、ハイフンの代わりに()であったり、ハイフンがなかったりのパターンにも対応する。

コード

import re

url = 'http://www.hogehoge'
result = urlfetch.fetch(url)
raw_html = result.content

pattern = r'^\d{2,4}-|)|)\d{2,4}-\d{3,4}'
tel_number = re.findall(pattern, raw_html)

普通の電話番号、フリーダイヤル、FAXがリストになって返ってくるのでどうやって電話番号だけにするかが課題。最初に電話番号、TEL、フリーダイヤルとかでsplitしておけばいいんじゃなかろうかと思われる。(このままではハマる。下のハマったを参照。)

エラー対応

error: unbalanced parenthesis

pattern = r'^\d{2,4}-|)|)\d{2,4}-\d{3,4}'の半角括弧閉じをエスケープしないとダメ
pattern = r'^\d{2,4}-|\)|)\d{2,4}-\d{3,4}'でOK。
ていうか、[-))]ってすればエスケープいらない。最終的にはバックスラッシュ必要だった。ハマったの最後を参照。
Unbalanced parenthesis python

ハマった

pattern = r'^\d{2,4}[-))]\d{2,4}-\d{3,4}'から苦闘した。

^つけっぱ事件

raw_html??0120-000-000なのにずっと先頭に^をつけっぱで検出できずムダにハマった。馬鹿ですね。

[-))]が上手くいかない

全角かっこのとじる「)」を検出できない。トチ狂って[-))]*.*としてみた。
当然、ダイヤル(0120)000-000 電話(03)0000-00000120)000-000 電話(03)0000-0000と抜き出される。
あれ?なんで??みたいな。
さらにさらに、最後に$をつけるという極めつけ。結果は変わりません。

raw_htmlを半角に変換する

import re
import unicodedata

url = 'http://www.hogehoge'
result = urlfetch.fetch(url)
raw_html = unicodedata.normalize('NFKC', result.content)

pattern = r'\d{2,4}[-)]*\d{2,4}-\d{3,4}$'
tel_number = re.findall(pattern, raw_html)
print tel_number

ダイヤル(0120)000-000 電話(03)0000-0000 -> 03)0000-0000
なんだかいいカンジになってきた。$が邪魔して、フリーダイヤル部分が取れてないので$をとる。

全角カッコをunicodeで書いてみる

ログにu'0120\uff09000-000\u3000\u96fb\u8a71\uff0803\uff090000-0000'を発見。もしかして。。。

pattern = r'[(\uff08]{0,1}\d{2,4}[-)\uff09]{0,1}\d{2,4}-{0,1}\d{3,4}'

で、いけるんじゃね? -> ダメ。
\でエスケープしたりいろいろ試したけど、結局unicodedata.normalize('NFKC', hoge)で半角にして処理することにした。

最終的なコード(正規表現部分のみ)

pattern = r'[(]{0,1}[0-9]{2,4}[)-(]{0,1}[0-9]{2,4}[)-]{0,1}[0-9]{3,4}'
  1. \dは[0-9]に変更。\dは知ってればわかるけど一見何なのかわからないので。
  2. 00(0000)0000に対応。

そうするとraise error, v # invalid expression。。。どこがエラーなのか?

pattern = r'[\(]{0,1}[0-9]{2,4}[\)\-\(]{0,1}[0-9]{2,4}[\)\-]{0,1}[0-9]{3,4}'

[]内の), -, (にバックスラッシュを入れて解決。
ダイヤル(0120)000-000 電話(03)0000-0000 -> [u'(0120)000-000', u'(03)0000-0000']
めでたしめでたし。

おまけ: ループを回すときはコンパイルしておく

pattern = re.compile(r'hogehoge')

for i in iter:
    # do something
    tel_number = pattern.findall(raw_html)

こうしておくと速いらしい。

参考

メールアドレスから電話番号まで!知っておきたいPHP正規表現6選
Pythonの正規表現の基本的な使い方

12
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
9