質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

2回答

3474閲覧

pythonの正規表現を使用して住所から都道府県などを抜き出したい。

YukiNishida-py

総合スコア6

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

0クリップ

投稿2020/01/08 14:29

前提・実現したいこと

今私は、
pythonとSeleniumというモジュールを使用して、GoogleMapから自動的にビル情報を抜き出す
プログラムを作成しております。

今私が苦戦しております内容は、

'''
東京都渋谷区恵比寿西1丁目12−14エイビスビルB1
大阪府大阪市北区角田町5−1楽天地ビル
奈良県奈良市東向中町28 奈良近鉄ビル3F
福岡県福岡市中央区天神1丁目12−20
'''

GoogleMapから抜き出した上記のようなビルの住所から、

・都道府県
・市区町村
・町名
・番地
・ビル名

をPythonの正規表現を用いて抜き出すという作業です。Pythonの正規表現の使い方がまだ初心者レベルで、どうしてもわからないのでご協力いただけるとありがたいです。

ちなみに、
・「都道府県」は、「都道府県」の文字まで出力
・「市区町村」は、「奈良市東向中町」のように、「市」で区切らずに「区町村」で区切る
・「町名」は、「天神1丁目」のように、「区町村」の文字の後から「目」の文字まで
・「番地」は、「12−20」と「28」の2パターンがあります。
・正規表現で抽出した文字列は、住所の文から毎回消去してビル名は最後に残るので、「ビル名」の処理は必要ありません。

そして、抜き出したい要素が見つからない場合には、「null」で出力したいのですが、ここに関してはまだ実装内容を細かく考え切れていません。

###プログラム全体のソースコード

### 質問サイト提出用のコード ## GoogleMapスクレイピング from selenium import webdriver import time from bs4 import BeautifulSoup as BS import re # クロームのドライバーを用意 driver = webdriver.Chrome() # クロームドライバーが「GoogleMap」urlを取得・開く url = 'https://www.google.co.jp/maps/' driver.get(url) # time.sleepは、ロード中の処理でエラーが起こらないように、処理を待機させるために使用 time.sleep(3) # 検索欄にキーワードを入力 keys = input('「郵便番号」の後にハイフンを入れて郵便番号を入力>') # データ入力 building_search_id = driver.find_element_by_id("searchboxinput") building_search_id.send_keys(keys) # サーチボックスに、keysにインプットされた要素を代入 time.sleep(3) # クリック search_button = driver.find_element_by_xpath("//*[@id='searchbox-searchbutton']") search_button.click() time.sleep(5) # 「付近を検索」をクリック near_search_button = driver.find_element_by_xpath("//*[@id='pane']/div/div[1]/div/div/div[5]/div[3]/div/button") near_search_button.click() time.sleep(5) # 「付近のビル」と入力 building_search_id = driver.find_element_by_id("searchboxinput") building_search_id.send_keys('付近のビル') time.sleep(3) # 「付近のビル」と入力し終わった後の検索蘭をクリック search_button2 = driver.find_element_by_xpath("//*[@id='searchbox-searchbutton']") search_button2.click() time.sleep(6) ## リンクを順にクリックするループ処理 while True: try: ## リンク数解析 link_list = [] page_source = driver.page_source # htmk解析 soup = BS(page_source, 'html.parser') link_text = soup.find(class_ = 'n7lv7yjyC35__left') # スクレイピング link_list.append(link_text.text.strip()) # スクレイピングした文字を一個一個分解する処理(n_gramを使用) # 下のfor文をdefの中に収納する可能性あり def n_gram(target, n): result = [] for i in range(0, len(target) - n + 1): result.append(target[i : i + n]) return result for i in link_list: target = i result = n_gram(target, 1) # 1文字ごとに分解してリストに収納したリスト if result[0] == '1': link1 = int(result[0]) link2_s = result[2:4] link2 = int("".join(link2_s)) elif result[2] == '〜': link1_s = result[0:2] link1 = int("".join(link1_s)) link2_s = result[3:5] link2 = int("".join(link2_s)) else: pass ## スクレイピングに使用する空のリストをここに設置 title_list = [] # スクレイピング要素がないリンクを飛ばすためのリスト address_list = [] # 検索結果のxpathというものでループを回しています path_front = '//*[@id="pane"]/div/div[1]/div/div/div[4]/div[1]/div[' count = 1 path_end = ']' roop_counter = 1 # ループを強制終了させるためのカウンター while roop_counter <= link2 - link1 + 1: # リンクを順にクリックさせています path = path_front + str(count) + path_end l = driver.find_element_by_xpath(path) l.click() time.sleep(5) if count == 1 or 3: # HTML解析 page_source = driver.page_source soup = BS(page_source, 'html.parser') # 例外ページをスキップ title = soup.find(class_ = 'GLOBAL__gm2-headline-5 section-hero-header-title-title') title_list.append(title.text.strip()) title_list_del = title_list.pop() # 内部の例外処理 if '-' not in title_list_del: pass else: count += 2 roop_counter += 1 back_button = driver.find_element_by_xpath('//*[@id="pane"]/div/div[1]/div/div/button/span') back_button.click() # 検索一覧に戻ります time.sleep(4) continue # スクレイピングの準備 address = soup.find_all(class_ = 'section-info-text') # 郵便番号をスクレイピングする処理 target = address[0].text.strip() address_result_old = n_gram(target, 1) # 分解した後のリスト address_result = [i for i in address_result_old if i != ' '] postal_code_list = address_result[0:9] postal_code = "".join(postal_code_list) # 郵便番号が完成 ## 正規表現を使用した住所解析 scraping_list = address_result[9:] # 一文字ずつ分けた、正規表現用のリスト scraping_str = "".join(scraping_list) # 正規表現用のリストを文字列に ###############ここから質問箇所です###################### # 「県」の抽出 Ken_match = re.match('', scraping_str) # matchの部分は適当に変えてください Ken = Ken_match.group() scraping_list = [i for i in scraping_list if i == Ken] # 「市区町村」の抽出 City_match = re.match('', scraping_str) # matchの部分は適当に変えてください City = City_match.group() scraping_list = [i for i in scraping_list if i == City] # 「町名」の抽出 Town_match = re.match('', scraping_str) # matchの部分は適当に変えください Town = Town_match.group() scraping_list = [i for i in scraping_list if i == Town] # 「番地」の抽出 num_match = re.match('', scraping_str) # matchの部分は適当に変えてください num = num_match.group() scraping_list = [i for i in scraping_list if i == num] #################ここまでが質問箇所です##################### # 「ビル名」の抽出 ## リストの残りを出力すれば完了 # 出力 print('--------------------------') print(scraping_str) # 正規表現の材料、あとで消す print(title.text.strip()) # タイトルの出力 最後は使わないかも print(postal_code) # 郵便番号の出力 print(Ken) # 「県名」の出力 print(City) # 「市区町村」の出力 print(Town) # 「町名」の出力 print(num) # 「番地」の出力 back_button = driver.find_element_by_xpath('//*[@id="pane"]/div/div[1]/div/div/button/span') back_button.click() # 検索一覧に戻ります count += 2 roop_counter += 1 time.sleep(5) # 次のページへ移動します next_button = driver.find_element_by_xpath('//*[@id="n7lv7yjyC35__section-pagination-button-next"]') next_button.click() time.sleep(7) except: driver.close() # 最後にブラウザを閉じて終了

質問したい部分のソースコード

Python3

1 # スクレイピングの準備 2 address = soup.find_all(class_ = 'section-info-text') 3 4 # 郵便番号をスクレイピングする処理 5 target = address[0].text.strip() 6 address_result_old = n_gram(target, 1) # 分解した後のリスト 7 address_result = [i for i in address_result_old if i != ' '] # 空白消す 8 postal_code_list = address_result[0:9] 9 postal_code = "".join(postal_code_list) # 郵便番号が完成 10 11 ## 正規表現を使用した住所解析 12 scraping_list = address_result[9:] # 一文字ずつ分けた、正規表現用のリスト 13 14 scraping_str = "".join(scraping_list) # 正規表現用のリストを文字列に 15 # 例(渋谷区恵比寿西1丁目12−14エイビスビルB1) 16 17 ###############ここから質問箇所です###################### 18 # 「県」の抽出 19 Ken_match = re.match('', scraping_str) # matchの部分は適当に変えてください 20 Ken = Ken_match.group() 21 scraping_list = [i for i in scraping_list if i == Ken]# マッチを消去 22 23 # 「市区町村」の抽出 24 City_match = re.match('', scraping_str) # matchの部分は適当に変えてください 25 City = City_match.group() 26 scraping_list = [i for i in scraping_list if i == City] 27 28 # 「町名」の抽出 29 Town_match = re.match('', scraping_str) # matchの部分は適当に変えください 30 Town = Town_match.group() 31 scraping_list = [i for i in scraping_list if i == Town] 32 33 # 「番地」の抽出 34 num_match = re.match('', scraping_str) # matchの部分は適当に変えてください 35 num = num_match.group() 36 scraping_list = [i for i in scraping_list if i == num] 37 #################ここまでが質問箇所です#####################

補足情報

Ken_match = re.match('', scraping_str)の、''の部分正規表現を考えていただきたいです。
re.matchの、matchは適宜適切なものに変えてください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

都道府県を分離、程度ならどうにかなりますが、その他に関してはあきらめたほうがよろしいかと思われます
程度問題となりますが、全く間違いなく分離、というのはムリかと。

投稿2020/01/08 15:43

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YukiNishida-py

2020/01/09 00:36

やはりそうですよね。 都道府県に関しては、精度を完璧にすることはできますが、他は完璧には難しそうですね。 ご回答ありがとうございます。
guest

0

ベストアンサー

都道府県・市区町村(自治体で切る)ならリストを用意するなりイレギュラーなところだけピックアップして正規表現にかけるなりで対応できますが(参考)、それ以降の住所については「町名+番地」だけでなく、

  • 市町村の次がいきなり番地(長野県木曽郡王滝村3623番地 王滝村役場)
  • 無番地(東京都青ヶ島村無番地 青ヶ島村役場)
  • 京都市内の通り名住所(京都市中京区寺町通御池上る上本能寺前町488 京都市役所)
  • 国有林内の林班(和歌山県伊都郡高野町大字高野山国有林第9林班ノは 高野山駅)
  • 岩手県の地割(岩手県紫波郡矢巾町第13地割123 矢巾町役場)
  • 北海道の条丁目・線号(札幌市中央区北1条西2丁目 札幌市役所)
  • 軽井沢の別荘番号など、公式の住所が役に立たないので独自に振っているケース
  • 道路式住居表示(東根市神町営団大通り47号 東根市営団公民館)

などなど、場所によって異なると言っても過言ではありません。パターン化するには、並大抵でない労力が必要となります。

投稿2020/01/09 00:26

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YukiNishida-py

2020/01/09 07:31

わざわざ例外や参考サイトまで記載してくださり、本当にありがとうございます。 maisumakun様の回答を見て、完璧なものではなく、ある程度の精度のものを作ることにいたしました。 本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問