[Python #23] 企業のホームページから電話番号の取得
こんにちは.PythonチームのA.Kです.
今回はインターンの業務内で,企業のURLからその企業の電話番号を取得する必要があったので,その手法について記述しようと思います.
スクレイピング
電話番号を取得すべき企業のURLは大量にありましたので,私はスクレイピングを用いて電話番号を取得することにしました.
ただ,一般的なスクレイピングはHTMLのclassやidから情報を入手するのですが,
今回は様々な企業のホームページに載っている電話番号を探索する必要があるので,
classやidの名前を指定して電話番号を取得することはできません.
したがって,ホームページのHTML全体から電話番号を探索する必要があります.
そのため,まずはそのURLのページソース全体を読み込みます.
from selenium import webdriver
options = webdriver.ChromeOptions()
driver = webdriver.Chrome(options=options)
url = "任意のURL"
driver.get(url)
pagesource = driver.page_source
これで変数pagesourceにはURLのHTMLの文字列が格納されています.
ここから,その文字列の中から電話番号を抽出していきます.
正規表現を用いた電話番号取得は精度が悪い!
URLから電話番号を取得する方法をネットで検索すると,正規表現を用いてサイトに載っている電話番号をパターン化し,
それに一致する文字列を電話番号だと判断して取得するという方法が多く載っていました.
それを信じて電話番号を取得しようとすると,
000-0000-000
00-0000-0000
0042-0047-00
のように電話番号に化けた番号の羅列が取得されてしまいました.
つまり,正規表現を利用して電話番号を取得しようとすると,あまり精度が良くないということです.
結局力づくのコードで対処
上記のように正規表現を利用して楽して,電話番号を取得することには失敗しましたので(私が利用した正規表現が悪かったのかもしれませんが...)
企業のホームページで掲載されうる電話番号の形式を全部記述して,それに一致する番号の羅列を電話番号をとして判断する方法を取りました.
電話番号の形式は以下の通りです.
0*-****-****
0***-****-****
(0*)****-*****
(0**)****-****
0***-***-****
(0**)***-****
0***-**-****
(0***)**-****
0***(**)****
0**(***)****
0*(****)****
0**(****)****
(0***)******
(0**)*******
(0*)********
(0**)********
***********
**********
*:0~9までの数字
以上のどれかのパターンに当てはまる数字の羅列を抽出するスクリプトは以下の通りになります.
def phone_number(pagesource):
string=pagesource
number_10 = ['0','1','2','3','4','5','6','7','8','9']
for i in range(len(string)):
if i < 15:
continue
elif string[i] in number_10 and string[i-1] in number_10 and string[i-2] in number_10 and string[i-3] == '-' and string[i-4] in number_10 and string[i-5] in number_10 and string[i-6] in number_10 and string[i-7] == '-' and string[i-8] == '0' and string[i-9] == '2' and string[i-10] == '1' and string[i-11] == '0':
digits = 11
answer[1] = string[i-digits]
for k in range(digits):
answer[1] = answer[1] + string[i-(digits-1-k)]
print('free dial')
print(answer[1])
elif string[i] in number_10 and string[i-1] in number_10 and string[i-2] in number_10 and string[i-3] in number_10:#末尾****
if string[i-4] == '-':#末尾-****
if string[i-5] in number_10 and string[i-6] in number_10:#末尾**-****
if string[i-7] in number_10 and string[i-8] in number_10:#末尾****-****
if string[i-9] == '-':#末尾-****-****
if string[i-10] in number_10 and string[i-11] =='0':#0*-****-****
digits = 11
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('00'):
answer[0] = ''
else:
break
elif string[i-10] in number_10 and string[i-11] in number_10 and string[i-12] == '0':#0**-****-****
digits = 12
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('000'):
answer[0] = ''
else:
break
elif string[i-9] ==')':#末尾)****-****
if string[i-10] in number_10 and string[i-11] == '0' and string[i-12] == '(':#(0*)****-****
digits = 12
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('(00)'):
answer[0] = ''
else:
break
elif string[i-10] in number_10 and string[i-11] in number_10 and string[i-12] == '0' and string[i-13] == '(':#(0**)****-****
digits = 13
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('(000)'):
answer[0] = ''
else:
break
elif string[i-7] in number_10:#末尾***-****
if string[i-8] == '-' and string[i-9] in number_10 and string[i-10] in number_10 and string[i-11] == '0':#0**-***-****
digits = 11
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('000'):
answer[0] = ''
else:
break
elif string[i-8] == ')' and string[i-9] in number_10 and string[i-10] in number_10 and string[i-11] == '0' and string[i-12] == '(':#(0**)***-****
digits = 12
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('(000)'):
answer[0] = ''
else:
break
elif string[i-7] == '-' and string[i-8] in number_10 and string[i-9] in number_10 and string[i-10] in number_10 and string[i-11] =='0':#0***-**-****
digits = 11
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('0120'):
answer[1] = answer[0]
answer[0] = ''
print('free dial')
print(answer[1])
if answer[0].startswith('0000'):
answer[0] = ''
else:
break
elif string[i-7] == '(' and string[i-8] in number_10 and string[i-9] in number_10 and string[i-10] in number_10 and string[i-11] =='0' and string[i-12] == ')':#(0***)**-****
digits = 12
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('(0120)'):
answer[1] = answer[0]
answer[0] = ''
print('free dial')
print(answer[1])
if answer[0].startswith('(0000)'):
answer[0] = ''
else:
break
elif string[i-4] == ')':#末尾)****
if string[i-5] in number_10 and string[i-6] in number_10:#末尾**)****
if string[i-7] =='(' and string[i-8] in number_10 and string[i-9] in number_10 and string[i-10] in number_10 and string[i-11] == '0':#0***(**)****
digits = 11
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('0120'):
answer.append(answer[0])
answer[0] = ''
print('free dial')
print(answer[1])
if answer[0].startswith('0000'):
answer[0] = ''
else:
break
elif string[i-7] in number_10 and string[i-8] =='(' and string[i-9] in number_10 and string[i-10] in number_10 and string[i-11] == '0':#0**(***)****
digits = 11
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('000'):
answer[0] = ''
else:
break
elif string[i-7] in number_10 and string[i-8] in number_10 and string[i-9] =='(' and string[i-10] in number_10 and string[i-11] == '0':#0*(****)****
digits = 11
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('00'):
answer[0] = ''
else:
break
elif string[i-7] in number_10 and string[i-8] in number_10 and string[i-9] =='(' and string[i-10] in number_10 and string[i-11] in number_10 and string[i-12] == '0':#0**(****)****
digits = 12
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('000'):
answer[0] = ''
else:
break
elif string[i-4] in number_10 and string[i-5] in number_10:#末尾******
if string[i-6] == ')' and string[i-7] in number_10 and string[i-8] in number_10 and string[i-9] in number_10 and string[i-10] == '0' and string[i-11] == '(':#(0***)******
digits = 11
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('(0120)'):
answer[1] = answer[0]
print('free dial')
print(answer[1])
answer[0] = ''
if answer[0].startswith('(0000)'):
answer[0] = ''
else:
break
elif string[i-6] in number_10 and string[i-7] == ')' and string[i-8] in number_10 and string[i-9] in number_10 and string[i-10] == '0' and string[i-11] == '(':#(0**)*******
digits = 11
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('(000)'):
answer[0] = ''
else:
break
elif string[i-6] in number_10 and string[i-7] in number_10 and string[i-8] == ')' and string[i-9] in number_10 and string[i-10] == '0' and string[i-11] == '(':#(0*)********
digits = 11
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('(00)'):
answer[0] = ''
else:
break
elif string[i-6] in number_10 and string[i-7] in number_10 and string[i-8] == ')' and string[i-9] in number_10 and string[i-10] in number_10 and string[i-11] == '0' and string[i-12] == '(':#(0**)********
digits = 12
answer[0] = string[i-digits]
for k in range(digits):
answer[0] = answer[0] + string[i-(digits-1-k)]
if answer[0].startswith('(000)'):
answer[0] = ''
else:
break
return answer
気合いの力づくスクリプトですが,これが結構精度良いんですよね.
関数の引数としてpagessourceを与えればそこに掲載されていた電話番号が返ってきます.
最後に
久しぶりにこんな脳筋コードを書いたことを共有したかったので記事にしました.
もっと調べれば,こんな冗長なコードを書かないでいい方法があるかもしれません.(ありそうですね笑)
ちなみに,「URLから電話番号をスクレイピング 方法」で検索した結果
「その自動処理は精度悪い」というような記事を見たことがあるので,URLから電話番号取得に成功できて,うれしい限りです.