Webスクレイピングで営業リストを作成する(4)
表の内容を処理に組み込んでいきます。
No | 対象 | 内容 | 対応方針 |
---|---|---|---|
1 | シート全体 | エラーデータの削除 | Excelで手動対応 |
2 | シート全体 | 重複データの削除 | Excelで手動対応 |
3 | シート全体 | A列にNoを振る | Excelで手動対応 |
4 | シート全体 | B列に各裁判所ページのURLを出力 | Seleniumで対応 |
5 | 裁判所名 | 不要文言除去『の所在地』 | Excelで手動対応 |
6 | 裁判所名 | 不要文言除去『(※)』 | Excelで手動対応 |
7 | 郵便番号 | 不要文言除去『〒』 | Excelで手動対応 |
8 | 郵便番号 | 文言置換「ー(長音)」→「-」 | Excelで手動対応 |
9 | 郵便番号 | 郵便番号が2個以上の場合、行を増やす | Seleniumで対応 |
10 | 郵便番号 | 大阪地裁・簡裁の取得時に、郵便番号・住所を分割 | Seleniumで対応 |
11 | 住所 | F,G列(住所1、住所2)追加 | Excel(数式)で対応 |
12 | 住所 | 住所とアクセス方法を分割 | Excel(数式)で対応 |
13 | 電話番号 | I~K列(窓口、番号、注意書き)追加 | Excel(数式)で対応 |
14 | 電話番号 | 電話番号と、それ以外の情報の分割 | Excel(数式)で対応 |
15 | 電話番号 | 電話番号が2個以上の場合、列を増やす | Seleniumで対応 |
1.Excelテンプレートの作成
まず、データ出力用のExcelシートを作成します。
ヘッダー
シートのヘッダーは、裁判所名、郵便番号、住所、電話番号に、
- No3:A列にNo
- No4:B列にURL欄追加
- No11:住所1、住所2を追加
- No13:窓口、番号、注意書きを追加
となります。
Excel関数の入力
- No12:住所とアクセス方法を分割
- No14:電話番号と、それ以外の情報の分割
の関数式をセルに入力します。
住所とアクセス方法を分割
住所:不要データの分割で使用した数式をベースに、セルF2に以下の数式を入力します。
=IF(MIN(IFERROR(SEARCH("(",E2),999),IFERROR(SEARCH("(",E2),999),IFERROR(SEARCH(CHAR(10),E2),999))=999,E2,LEFT(E2,MIN(IFERROR(SEARCH("(",E2),999),IFERROR(SEARCH("(",E2),999),IFERROR(SEARCH(CHAR(10),E2),999))-1))
セルG2に以下の数式を入力します。
=SUBSTITUTE(E2,F2,"")
電話番号と、それ以外の情報の分割
電話番号:不要データの分割で使用した数式をベースに、セルI2に以下の数式を入力します。
=LEFT(H2,MAX(IFERROR(SEARCH(":",H2),0),IFERROR(SEARCH(":",H2),0)))
セルJ2に以下の数式を入力します。
=IF(MIN(IFERROR(SEARCH("(",SUBSTITUTE(H2,I2,"")),999),IFERROR(SEARCH("(",SUBSTITUTE(H2,I2,"")),999),IFERROR(SEARCH(CHAR(10),SUBSTITUTE(H2,I2,"")),999))=999,SUBSTITUTE(H2,I2,""),LEFT(SUBSTITUTE(H2,I2,""),MIN(IFERROR(SEARCH("(",SUBSTITUTE(H2,I2,"")),999),IFERROR(SEARCH("(",SUBSTITUTE(H2,I2,"")),999),IFERROR(SEARCH(CHAR(10),SUBSTITUTE(H2,I2,"")),999))-1))
セルK2に以下の数式を入力します。
=SUBSTITUTE(SUBSTITUTE(H2,I2,""),J2,"")
行コピー
これらの内容を各行にコピーします。
2.スクリプトの修正
元のスクリプト
# -*- coding:utf-8 -*- from selenium import webdriver import xlwings as xw # Chromeドライバ起動 driver_path = r'D:\SeleniumCodeChecker\driver\chromedriver.exe' driver = webdriver.Chrome(executable_path=driver_path) # Excelオープン book_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地.xlsx' wb1 = xw.Book() ws1 = wb1.sheets[0] #列幅の設定 xw.Range('a:a').column_width = 25 xw.Range('b:b').column_width = 9 xw.Range('c:c').column_width = 50 xw.Range('d:d').column_width = 20 #ヘッダ出力 ws1.cells(1, 1).value = '裁判所' ws1.cells(1, 2).value = '郵便番号' ws1.cells(1, 3).value = '住所' ws1.cells(1, 4).value = '電話番号' k=2 #Excelシートの行 driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') count_i = len(driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')) for i in range(count_i): driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')[i].click() #element(s) #表のヘッダーの相違でtrの序数が変わる if len(driver.find_elements_by_xpath('//table/thead')) > 0: j = 1 else: j = 3 link = None #地域画面のリンク要素 #通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') #松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') #岡山 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: while len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: before_handle = driver.current_window_handle # 現在のハンドルを保存 driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]').click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) # 詳細画面も独自形式 ws1.cells(k, 1).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//caption').text ws1.cells(k, 2).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[1]/td').text ws1.cells(k, 3).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[2]/td').text ws1.cells(k, 4).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[3]/td').text #地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() #ブラウザの戻る j += 1 k += 1 #知財高裁 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) == 0: ws1.cells(k, 1).value = 'エラー' ws1.cells(k, 2).value = 'i=' + str(i) k += 1 if len(driver.window_handles) > 1: before_handle = driver.current_window_handle # ハンドルを保存 driver.switch_to.window(driver.window_handles[1]) driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す #通常ケース&松江 while link is not None: #リンク先がpdfの場合は遷移無し url = link.get_attribute('href') if url[len(url)-4:] == '.pdf': #urlの末尾4文字が'.pdf' ws1.cells(k, 1).value = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a').text ws1.cells(k, 2).value = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[2]').text ws1.cells(k, 3).value = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[3]').text ws1.cells(k, 4).value = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[5]').text else: before_handle = driver.current_window_handle # 現在のハンドルを保存 link.click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) #Excel出力 try: ws1.cells(k, 1).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text except: # 表上部の裁判所が存在しない場合はヘッダー部から編集 ws1.cells(k, 1).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-Header"]/div/h2').text ws1.cells(k, 2).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text ws1.cells(k, 3).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text #電話番号が存在しないケースあり(横浜地方裁判所) if len(driver.find_elements_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[3]/dd')) > 0: ws1.cells(k, 4).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[3]/dd').text #地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() #ブラウザの戻る j += 1 k += 1 # while文の次の条件を設定 #通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') else: link = None ws1.cells(k, 1).select() # 表示デモ用 #Excel保存 wb1.save(book_path) wb1.close()
Excelシートの変更を反映
新たなExcelシートに合うように、元のスクリプトを変更します。
ヘッダ出力を削除
ヘッダ情報は、あらかじめExcelシートに記入します。列幅も後で調整しますので、13~22行を削除します。
列順の変更を反映
列順は次のようになります。
項目 | 旧 | 新 |
裁判所名 | A列(1列目) | C列(3列目) |
郵便番号 | B列(2列目) | D列(4列目) |
住所 | C列(3列目) | E列(5列目) |
電話番号 | D列(4列目) | H列(8列目) |
上記スクリプトの網掛け部分を変更します。
Excelシートは既存のファイルを利用する
これまでは、Excelブックを新規で作成し、最後に保存していました。
元の処理
# Excelオープン
book_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地.xlsx'
wb1 = xw.Book()
ws1 = wb1.sheets[0]
#Excel保存
wb1.save(book_path)
wb1.close()
これをテンプレートとなるファイルを開いて、別名で保存するように変更します。
修正内容
# Excelオープン
template_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地テンプレート.xlsx'
wb1 = xw.Book(template_path)
ws1 = wb1.sheets[0]
#Excel保存
book_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地.xlsx'
wb1.save(book_path)
wb1.close()
修正スクリプト
# -*- coding:utf-8 -*- from selenium import webdriver import xlwings as xw # Chromeドライバ起動 driver_path = r'D:\SeleniumCodeChecker\driver\chromedriver.exe' driver = webdriver.Chrome(executable_path=driver_path) # Excelオープン template_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地テンプレート.xlsx' wb1 = xw.Book(template_path) ws1 = wb1.sheets[0] k=2 #Excelシートの行 driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') count_i = len(driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')) for i in range(count_i): driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')[i].click() #element(s) #表のヘッダーの相違でtrの序数が変わる if len(driver.find_elements_by_xpath('//table/thead')) > 0: j = 1 else: j = 3 link = None #地域画面のリンク要素 #通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') #松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') #岡山 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: while len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: before_handle = driver.current_window_handle # 現在のハンドルを保存 driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]').click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) # 詳細画面も独自形式 ws1.cells(k, 3).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//caption').text ws1.cells(k, 4).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[1]/td').text ws1.cells(k, 5).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[2]/td').text ws1.cells(k, 8).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[3]/td').text #地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() #ブラウザの戻る j += 1 k += 1 #知財高裁 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) == 0: ws1.cells(k, 3).value = 'エラー' ws1.cells(k, 4).value = 'i=' + str(i) k += 1 if len(driver.window_handles) > 1: before_handle = driver.current_window_handle # ハンドルを保存 driver.switch_to.window(driver.window_handles[1]) driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す #通常ケース&松江 while link is not None: #リンク先がpdfの場合は遷移無し url = link.get_attribute('href') if url[len(url)-4:] == '.pdf': #urlの末尾4文字が'.pdf' ws1.cells(k, 3).value = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a').text ws1.cells(k, 4).value = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[2]').text ws1.cells(k, 5).value = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[3]').text ws1.cells(k, 8).value = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[5]').text else: before_handle = driver.current_window_handle # 現在のハンドルを保存 link.click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) #Excel出力 try: ws1.cells(k, 3).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text except: # 表上部の裁判所が存在しない場合はヘッダー部から編集 ws1.cells(k, 3).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-Header"]/div/h2').text ws1.cells(k, 4).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text ws1.cells(k, 5).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text #電話番号が存在しないケースあり(横浜地方裁判所) if len(driver.find_elements_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[3]/dd')) > 0: ws1.cells(k, 8).value = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[3]/dd').text #地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() #ブラウザの戻る j += 1 k += 1 # while文の次の条件を設定 #通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') else: link = None ws1.cells(k, 1).select() # 表示デモ用 #Excel保存 book_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地.xlsx' wb1.save(book_path) wb1.close()
Excel出力を関数化
後の修正でExcel出力部分を変更するのですが、今のスクリプトは色々な箇所で出力しているため、変更する箇所が多岐に渡ります。
今のうちに共通関数にして、Excel出力を1ヵ所にまとめておけば、変更がある場合も、修正は1か所で済みます。
Excel出力用の関数を作って、Excel出力する部分は、その関数を呼ぶように変更します。
Excel出力関数
def output(ws, row, col, str):
ws.cells(row, col).value = str
ws:ワークシート、row:行番号、col:列番号、str:出力内容
修正スクリプト
# -*- coding:utf-8 -*- from selenium import webdriver import xlwings as xw def main(): # Chromeドライバ起動 driver_path = r'D:\SeleniumCodeChecker\driver\chromedriver.exe' driver = webdriver.Chrome(executable_path=driver_path) # Excelオープン template_path = \ r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地テンプレート.xlsx' wb1 = xw.Book(template_path) ws1 = wb1.sheets[0] k=2 #Excelシートの行 driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') count_i = len(driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')) for i in range(count_i): driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')[i].click() #element(s) #表のヘッダーの相違でtrの序数が変わる if len(driver.find_elements_by_xpath('//table/thead')) > 0: j = 1 else: j = 3 link = None #地域画面のリンク要素 #通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') #松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') #岡山 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: while len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: # 現在のハンドルを保存 before_handle = driver.current_window_handle driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]').click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) # 詳細画面も独自形式 output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//caption').text) output(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[1]/td').text) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[2]/td').text) output(ws1, k, 8, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[3]/td').text) #地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() #ブラウザの戻る j += 1 k += 1 #知財高裁 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) == 0: output(ws1, k, 3, 'エラー') output(ws1, k, 4, 'i=' + str(i)) k += 1 if len(driver.window_handles) > 1: before_handle = driver.current_window_handle # ハンドルを保存 driver.switch_to.window(driver.window_handles[1]) driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す #通常ケース&松江 while link is not None: #リンク先がpdfの場合は遷移無し url = link.get_attribute('href') if url[len(url)-4:] == '.pdf': #urlの末尾4文字が'.pdf' output(ws1, k, 3, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a').text) output(ws1, k, 4, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[2]').text) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[3]').text) output(ws1, k, 8, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[5]').text) else: # 現在のハンドルを保存 before_handle = driver.current_window_handle link.click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) #Excel出力 try: output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text) except: # 表上部の裁判所が存在しない場合はヘッダー部から編集 output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-Header"]/div/h2').text) output(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text) #電話番号が存在しないケースあり(横浜地方裁判所) if len(driver.find_elements_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[3]/dd')) > 0: output(ws1, k, 8, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[3]/dd').text) #地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() #ブラウザの戻る j += 1 k += 1 # while文の次の条件を設定 #通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') else: link = None ws1.cells(k, 1).select() # 表示デモ用 #Excel保存 book_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地.xlsx' wb1.save(book_path) wb1.close() #Excel出力関数 def output(ws, row, col, str): ws.cells(row, col).value = str #main関数 if __name__ == "__main__": main()
あわせて主処理をmain関数にしています。
3.スクリプトの改良
上のスクリプトに、以下の対応を追加します。
- No4:B列に各裁判所ページのURLを出力
- No9:郵便番号が2個以上の場合、行を増やす
- No10:大阪地裁・簡裁の取得時に、郵便番号・住所を分割
- No15:電話番号が2個以上の場合、列を増やす
ページのURLを出力
B列(2列目)にページのURLを出力します。
表示しているページのURLは【driver.current_url】で取得できます。
詳細画面毎の処理で、Excelに出力している部分に以下のコードを加えます。
output(ws1, k, 2, driver.current_url)
郵便番号が複数の場合、行を増やす
郵便番号(新フォーマットではD列)の内容が複数ある場合、行を追加します。
対象データ
複数個の判定
2個以上あるかどうかの判定は、「福島地裁」は全角カンマ、それ以外は改行です。
しかし、改行で分割するデータの中にもカンマがあるので、
- 改行で分割できた場合、2個以上あると判定
- 1で分割できなかった場合で、全角カンマで分割できた場合、2個以上あると判定
というロジックになります。
#改行で分割して配列(list)に保存
l_out = str.splitlines()
#改行がない場合は「,(全角カンマ)」で分割
if len(l_out) == 1:
#配列の要素が1個の場合
l_out = str.split(',')
Excelシートに出力
次に郵便番号をExcelシートに出力します。
上で配列(list)に格納されている郵便番号の個数分、Excel出力します。
複数個出力する場合は、セルの行番号を増やします。
for i in range(len(l_out)):
ws.cells(行番号 + i, 列番号).value = l_out[i]
この処理を関数として実装します。
関数の戻り値は、郵便番号の個数(表示に必要な行数)とします。
郵便番号を出力する関数
def out_yubin(ws, row, col, str):
#改行で分割して配列(list)に保存
l_out = str.splitlines()
#改行がない場合は「,(全角カンマ)」で分割
if len(l_out) == 1:
l_out = str.split(',')
for i in range(len(l_out)):
ws.cells(row + i, col).value = l_out[i]
return len(l_out)
他の項目
郵便番号が2個以上で行が増えた場合、郵便番号以外の項目についても、増やす必要があります。
ただし、郵便番号以外の項目は、2行目以降も同じ内容を出力します。
よって、郵便番号の個数分だけ、同じ内容を出力することになります。
Excel出力関数を、繰り返し出力できるように修正します。
def output(ws, row, col, str, num):
#num:出力する行数
for i in range(num):
ws.cells(row + i, col).value = str
出力する行数(郵便番号の個数)は、郵便番号を出力する関数(out_yubin)の戻り値です。
行数のカウント
これまで1行ずつ増やしていたExcelの行数を、numだけ増やすように変更します。
修正前
k += 1
修正後
k += num
修正スクリプト
ここまでの内容をスクリプトに反映させます。
# -*- coding:utf-8 -*- from selenium import webdriver import xlwings as xw def main(): # Chromeドライバ起動 driver_path = r'D:\SeleniumCodeChecker\driver\chromedriver.exe' driver = webdriver.Chrome(executable_path=driver_path) # Excelオープン template_path = \ r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地テンプレート.xlsx' wb1 = xw.Book(template_path) ws1 = wb1.sheets[0] k = 2 # Excelシートの行 driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') count_i = len(driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')) for i in range(count_i): driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')[i].click() #element(s) # 表のヘッダーの相違でtrの序数が変わる if len(driver.find_elements_by_xpath('//table/thead')) > 0: j = 1 else: j = 3 link = None # 地域画面のリンク要素 # 通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') # 岡山 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: while len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: # 現在のハンドルを保存 before_handle = driver.current_window_handle driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]').click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) # 詳細画面も独自形式 num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[1]/td').text) output(ws1, k, 2, driver.current_url, num) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//caption').text, num) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[2]/td').text, num) output(ws1, k, 8, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[3]/td').text, num) # 地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() # ブラウザの戻る j += 1 k += num # 知財高裁 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) == 0: output(ws1, k, 2, driver.current_url, 1) output(ws1, k, 3, 'エラー', 1) output(ws1, k, 4, 'i=' + str(i), 1) k += 1 if len(driver.window_handles) > 1: before_handle = driver.current_window_handle # ハンドルを保存 driver.switch_to.window(driver.window_handles[1]) driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す # 通常ケース&松江 while link is not None: # リンク先がpdfの場合は遷移無し url = link.get_attribute('href') if url[len(url) - 4:] == '.pdf': # urlの末尾4文字が'.pdf' num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[2]').text) output(ws1, k, 2, driver.current_url, num) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a').text, num) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[3]').text, num) output(ws1, k, 8, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[5]').text, num) else: # 現在のハンドルを保存 before_handle = driver.current_window_handle link.click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text) output(ws1, k, 2, driver.current_url, num) # Excel出力 try: output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text, num) except: # 表上部の裁判所が存在しない場合はヘッダー部から編集 output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-Header"]/div/h2').text, num) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text, num) # 電話番号が存在しないケースあり(横浜地方裁判所) if len(driver.find_elements_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[3]/dd')) > 0: output(ws1, k, 8, driver.find_element_by_xpath (\ '//div[@id="VcArea-MainColum"]/div/dl[3]/dd').text, num) # 地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() # ブラウザの戻る j += 1 k += num # while文の次の条件を設定 # 通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') else: link = None ws1.cells(k, 1).select() # 表示デモ用 # Excel保存 book_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地.xlsx' wb1.save(book_path) wb1.close() # Excel出力関数 def output(ws, row, col, str, num): #num:行数 for i in range(num): ws.cells(row + i, col).value = str #郵便番号出力 def out_yubin(ws, row, col, str): #改行で分割して配列(list)に保存 l_out = str.splitlines() #改行がない場合は「,(全角カンマ)」で分割 if len(l_out) == 1: l_out = str.split(',') for i in range(len(l_out)): ws.cells(row + i, col).value = l_out[i] return len(l_out) # main関数 if __name__ == "__main__": main()
最初に、郵便番号の個数を取得する必要がありますので、Excelに出力する順番を変更しています。
大阪地裁・簡裁の対応
対象画面
標準データでは郵便番号が記載されている一番目の欄に、郵便番号と住所が記載されています。
郵便番号と住所の取得
1段目から郵便番号と住所を分割して出力します。
#郵便番号と住所の取得
strbuf = driver.find_element_by_xpath('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text
l_str = strbuf.splitlines()
#改行で分割
yubin = l_str[0][6:]
#「郵便番号:〒999-9999」から7文字目以降(数値部分)を取得
add = l_str[1][3:]
#「住所:XXXXXXXX」から4文字目以降(住所部分)を取得
電話番号の取得
電話番号は2段目から編集します。
driver.find_element_by_xpath('//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text
修正スクリプト
1段目に「住所:」という文言が含まれる場合、上記の処理を行います。
# -*- coding:utf-8 -*- from selenium import webdriver import xlwings as xw def main(): # Chromeドライバ起動 driver_path = r'D:\SeleniumCodeChecker\driver\chromedriver.exe' driver = webdriver.Chrome(executable_path=driver_path) # Excelオープン template_path = \ r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地テンプレート.xlsx' wb1 = xw.Book(template_path) ws1 = wb1.sheets[0] k = 2 # Excelシートの行 driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') count_i = len(driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')) for i in range(count_i): if i < 61: continue driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')[i].click() #element(s) # 表のヘッダーの相違でtrの序数が変わる if len(driver.find_elements_by_xpath('//table/thead')) > 0: j = 1 else: j = 3 link = None # 地域画面のリンク要素 # 通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') # 岡山 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: while len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: # 現在のハンドルを保存 before_handle = driver.current_window_handle driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]').click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) # 詳細画面も独自形式 num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[1]/td').text) output(ws1, k, 2, driver.current_url, num) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//caption').text, num) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[2]/td').text, num) output(ws1, k, 8, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[3]/td').text, num) # 地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() # ブラウザの戻る j += 1 k += num # 知財高裁 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) == 0: output(ws1, k, 2, driver.current_url, 1) output(ws1, k, 3, 'エラー', 1) output(ws1, k, 4, 'i=' + str(i), 1) k += 1 if len(driver.window_handles) > 1: before_handle = driver.current_window_handle # ハンドルを保存 driver.switch_to.window(driver.window_handles[1]) driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す # 通常ケース&松江 while link is not None: # リンク先がpdfの場合は遷移無し url = link.get_attribute('href') if url[len(url) - 4:] == '.pdf': # urlの末尾4文字が'.pdf' num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[2]').text) output(ws1, k, 2, driver.current_url, num) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a').text, num) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[3]').text, num) output(ws1, k, 8, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[5]').text, num) else: # 現在のハンドルを保存 before_handle = driver.current_window_handle link.click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) #大阪地裁・簡裁 if '住所:' in driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text: num = 1 output(ws1, k, 2, driver.current_url, 1) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text, 1) #郵便番号欄に住所も含まれている strbuf = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text l_str = strbuf.splitlines() yubin = l_str[0][6:] #「郵便番号:〒」を削除 add = l_str[1][3:] #「住所:」を削除 output(ws1, k, 4, yubin, num) output(ws1, k, 5, add, num) output(ws1, k, 8, driver.find_element_by_xpath (\ '//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text, num) else: num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text) output(ws1, k, 2, driver.current_url, num) # Excel出力 try: output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text, num) except: # 表上部の裁判所が存在しない場合はヘッダー部から編集 output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-Header"]/div/h2').text, num) output(ws1, k, 5, driver.find_element_by_xpath (\ '//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text, num) # 電話番号が存在しないケースあり(横浜地方裁判所) if len(driver.find_elements_by_xpath( \ '//div[@id="VcArea-MainColum"]/div/dl[3]/dd')) > 0: output(ws1, k, 8, driver.find_element_by_xpath( \ '//div[@id="VcArea-MainColum"]/div/dl[3]/dd').text,num) # 地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() # ブラウザの戻る j += 1 k += num # while文の次の条件を設定 # 通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') else: link = None ws1.cells(k, 1).select() # 表示デモ用 # Excel保存 book_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地.xlsx' wb1.save(book_path) wb1.close() # Excel出力関数 def output(ws, row, col, str, num): #num:行数 for i in range(num): ws.cells(row + i, col).value = str #郵便番号出力 def out_yubin(ws, row, col, str): #改行で分割して配列(list)に保存 l_out = str.splitlines() #改行がない場合は「,(全角カンマ)」で分割 if len(l_out) == 1: l_out = str.split(',') for i in range(len(l_out)): ws.cells(row + i, col).value = l_out[i] return len(l_out) # main関数 if __name__ == "__main__": main()
電話番号が複数の場合、列を増やす
対象データ
改行で電話番号の分割が可能です。
Excelテンプレート
電話番号の件数に応じて、H列~K列の内容を右側に増やします。
対応内容
- 改行で分割できた場合、2件以上あると判定します。
- 複数個の場合は、L列に2件目の電話番号を出力します。
- セルI,J,K列を、セルM,N,O列にコピーします。
- 3件以上の場合は、2~3の処理を繰り返します。
郵便番号と同様に、電話番号を出力する関数を作成します。
電話番号を出力する関数
def out_tel(ws, row, col, str, num): #num:行数
#改行で分割して配列(list)に保存
l_out = str.splitlines()
for i in range(num):
for j in range(len(l_out)):
k = col + 4*j #出力列番号
ws.cells(row + i, k).value = l_out[j]
if j > 0:
if j == 1:
rng_copy = xw.Range(ws.cells(row + i, col + 1), ws.cells(row + i, col + 3))
rng_paste = xw.Range(ws.cells(row + i, k + 1), ws.cells(row + i, k + 3))
rng_copy.copy(rng_paste) #rng_copyをrng_pasteにセルのコピー
xlwingsのRangeオブジェクトを使用しています。
import xlwings as xw
Range領域 = xw.Range(開始セル, 終了セル)
セルのコピーはRangeオブジェクトのcopyメソッドを使用しています。
コピー元.copy(コピー先)
修正スクリプト
# -*- coding:utf-8 -*- from selenium import webdriver import xlwings as xw def main(): # Chromeドライバ起動 driver_path = r'D:\SeleniumCodeChecker\driver\chromedriver.exe' driver = webdriver.Chrome(executable_path=driver_path) # Excelオープン template_path = \ r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地テンプレート.xlsx' wb1 = xw.Book(template_path) ws1 = wb1.sheets[0] k = 2 # Excelシートの行 driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') count_i = len(driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')) for i in range(count_i): driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')[i].click() #element(s) # 表のヘッダーの相違でtrの序数が変わる if len(driver.find_elements_by_xpath('//table/thead')) > 0: j = 1 else: j = 3 link = None # 地域画面のリンク要素 # 通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') # 岡山 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: while len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: # 現在のハンドルを保存 before_handle = driver.current_window_handle driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]').click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) # 詳細画面も独自形式 num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[1]/td').text) output(ws1, k, 2, driver.current_url, num) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//caption').text, num) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[2]/td').text, num) out_tel(ws1, k, 8, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[3]/td').text, num) # 地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() # ブラウザの戻る j += 1 k += num # 知財高裁 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) == 0: output(ws1, k, 2, driver.current_url, 1) output(ws1, k, 3, 'エラー', 1) output(ws1, k, 4, 'i=' + str(i), 1) k += 1 if len(driver.window_handles) > 1: before_handle = driver.current_window_handle # ハンドルを保存 driver.switch_to.window(driver.window_handles[1]) driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す # 通常ケース&松江 while link is not None: # リンク先がpdfの場合は遷移無し url = link.get_attribute('href') if url[len(url) - 4:] == '.pdf': # urlの末尾4文字が'.pdf' num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[2]').text) output(ws1, k, 2, driver.current_url, num) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a').text, num) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[3]').text, num) output(ws1, k, 8, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[5]').text, num) else: # 現在のハンドルを保存 before_handle = driver.current_window_handle link.click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) #大阪地裁・簡裁 if '住所:' in driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text: num = 1 output(ws1, k, 2, driver.current_url, 1) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text, 1) #郵便番号欄に住所も含まれている strbuf = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text l_str = strbuf.splitlines() yubin = l_str[0][6:] #「郵便番号:〒」を削除 add = l_str[1][3:] #「住所:」を削除 output(ws1, k, 4, yubin, num) output(ws1, k, 5, add, num) out_tel(ws1, k, 8, driver.find_element_by_xpath (\ '//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text, num) else: num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text) output(ws1, k, 2, driver.current_url, num) # Excel出力 try: output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text, num) except: # 表上部の裁判所が存在しない場合はヘッダー部から編集 output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-Header"]/div/h2').text, num) output(ws1, k, 5, driver.find_element_by_xpath (\ '//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text, num) # 電話番号が存在しないケースあり(横浜地方裁判所) if len(driver.find_elements_by_xpath( \ '//div[@id="VcArea-MainColum"]/div/dl[3]/dd')) > 0: out_tel(ws1, k, 8, driver.find_element_by_xpath( \ '//div[@id="VcArea-MainColum"]/div/dl[3]/dd').text,num) # 地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() # ブラウザの戻る j += 1 k += num # while文の次の条件を設定 # 通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') else: link = None ws1.cells(k, 1).select() # 表示デモ用 # Excel保存 book_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地.xlsx' wb1.save(book_path) wb1.close() # Excel出力関数 def output(ws, row, col, str, num): #num:行数 for i in range(num): ws.cells(row + i, col).value = str #郵便番号出力 def out_yubin(ws, row, col, str): #改行で分割して配列(list)に保存 l_out = str.splitlines() #改行がない場合は「,(全角カンマ)」で分割 if len(l_out) == 1: l_out = str.split(',') for i in range(len(l_out)): ws.cells(row + i, col).value = l_out[i] return len(l_out) #電話番号出力 def out_tel(ws, row, col, str, num): #num:行数 #改行で分割して配列(list)に保存 l_out = str.splitlines() for i in range(num): for j in range(len(l_out)): k = col + 4*j #出力列番号 ws.cells(row + i, k).value = l_out[j] if j > 0: if j == 1: rng_copy = xw.Range(ws.cells(row + i, col + 1), \ ws.cells(row + i, col + 3)) rng_paste = xw.Range(ws.cells(row + i, k + 1), \ ws.cells(row + i, k + 3)) rng_copy.copy(rng_paste) #rng_copyをrng_pasteにコピー # main関数 if __name__ == "__main__": main()
スクリプトの実行
スクリプトを実行します。
結果の確認
結果を確認します。
ページのURLを出力
B列にページのURLが出力されています。
ただし、上の例ではURLが文字としてあるだけで、クリックしてもWebサイトにリンクしません。ハイパーリンクの設定をします。
郵便番号が複数件
「函館地方・家庭・簡易裁判所」の郵便番号が分割されて、3行で表示されています。
大阪地裁・簡裁
郵便番号、住所、電話番号が正しく編集されています。
電話番号が複数件
電話番号が分割されて、2件目以降も出力されています。
4.Excelシートの修正
エラーケース
電話番号の分割で、標準データのみを対象としたため、標準外データで上手く出力できていない箇所があります。
分割の例外
「PDF:99KB」のように、「:(コロン)」が含まれているため、電話番号が分割されてしまっています。
「PDF:」については、「:」を無視するようにします。
区切り文字の追加
電話番号が2件以上入っている場合は分割対象外にしていましたが、列を追加して出力するようにした結果、コロン以外の区切り文字が現れました。
分割する区切り文字に「) (全角右かっこ+半角スペース)」を加えます。
区切り文字なし
電話番号が存在しないケースで、区切り文字がない場合、窓口(I列)ではなく、番号(J列)に出力されています。
区切り文字がない場合は、I列にH列の内容をそのまま出力します。
ただし、以下のように、区切り文字がなく、電話番号が記載されている場合(数字で始まる場合)はI2は「""(空文字)」とします。
数式の修正
セルI2の数式を変更します。
元の数式
=LEFT(H2,MAX(IFERROR(SEARCH(":",H2),0),IFERROR(SEARCH(":",H2),0)))
手順1
MAX関数内の【IFERROR(SEARCH(“:",H2),0)】【IFERROR(SEARCH(“:",H2),0)】は、電話番号(H2)に「:」「:」が含まれる場合の区切り位置を返しています。
今回、区切り文字に「) 」を追加したので、MAX関数内に【IFERROR(SEARCH(“) “,H2),0)】を追加します。
=LEFT(H2,MAX(IFERROR(SEARCH(":",H2),0),IFERROR(SEARCH(":",H2),0),IFERROR(SEARCH(") ",H2),0)))
手順2
区切り文字がない(「:」「:」「) 」の検索結果が全てエラー)場合は、H列の内容をそのまま出力します。
=IF(AND(ISERR(SEARCH(":",H2)),ISERR(SEARCH(":",H2)),ISERR(SEARCH(") ",H2))),H2,LEFT(H2,MAX(IFERROR(SEARCH(":",H2),0),IFERROR(SEARCH(":",H2),0),IFERROR(SEARCH(") ",H2),0))))
手順3
電話番号(H2)に「PDF:」が含まれる場合、「:」を無視します。
検索対象(H2)から、あらかじめ「:」を取り除くために、【SUBSTITUTE(H2,"PDF:","PDF*")】でH2の中身の「PDF:」を「PDF*」に置換します。
=IF(AND(ISERR(SEARCH(":",SUBSTITUTE(H2,"PDF:","PDF*"))),ISERR(SEARCH(":",SUBSTITUTE(H2,"PDF:","PDF*"))),ISERR(SEARCH(") ",SUBSTITUTE(H2,"PDF:","PDF*")))),H2,LEFT(SUBSTITUTE(H2,"PDF:","PDF*"),MAX(IFERROR(SEARCH(":",SUBSTITUTE(H2,"PDF:","PDF*")),0),IFERROR(SEARCH(":",SUBSTITUTE(H2,"PDF:","PDF*")),0),IFERROR(SEARCH(") ",SUBSTITUTE(H2,"PDF:","PDF*")),0))))
手順4
最後に先頭が数字で始まる場合はH2の内容をそのまま表示します。
セルH2の先頭1文字が数字かどうかを【ISNUMBER(VALUE(LEFT(H2,1)))】で判定します。
VALUE関数でいったんLEFT(H2,1)の内容を数値に変換し、ISNUMBERで実際に数値かどうかを判定しています。
=IF(ISNUMBER(VALUE(LEFT(H2,1))),"",IF(AND(ISERR(SEARCH(":",SUBSTITUTE(H2,"PDF:","PDF*"))),ISERR(SEARCH(":",SUBSTITUTE(H2,"PDF:","PDF*"))),ISERR(SEARCH(") ",SUBSTITUTE(H2,"PDF:","PDF*")))),H2,LEFT(SUBSTITUTE(H2,"PDF:","PDF*"),MAX(IFERROR(SEARCH(":",SUBSTITUTE(H2,"PDF:","PDF*")),0),IFERROR(SEARCH(":",SUBSTITUTE(H2,"PDF:","PDF*")),0),IFERROR(SEARCH(") ",SUBSTITUTE(H2,"PDF:","PDF*")),0)))))
この内容をExcelテンプレートに反映します。
5.完成スクリプト
ハイパーリンクの設定
URL欄(B列)をクリックすれば、該当ページにジャンプするように『ハイパーリンクの設定』をします。
スクリプトでURL出力時に、Excelの「HYPERLINK関数」を出力するようにします。
URLを出力する関数
def out_url(ws, row, col, str, num):
for i in range(num):
ws.cells(row + i, col).formula = '=HYPERLINK("' + str + '")'
HYPERLINK関数の中の「"(ダブルクォーテーション)」は、Excelシート上で「=HYPERLINK(“https://~")」と、URLを囲む記号なので忘れないようにします。
完成スクリプト(最終版)
# -*- coding:utf-8 -*- from selenium import webdriver import xlwings as xw def main(): # Chromeドライバ起動 driver_path = r'D:\SeleniumCodeChecker\driver\chromedriver.exe' driver = webdriver.Chrome(executable_path=driver_path) # Excelオープン template_path = \ r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地テンプレート.xlsx' wb1 = xw.Book(template_path) ws1 = wb1.sheets[0] k = 2 # Excelシートの行 driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') count_i = len(driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')) for i in range(count_i): driver.get('https://www.courts.go.jp/courthouse/map_tel/index.html') driver.find_elements_by_xpath \ ('//a[contains(text(),\'所在地・代表電話\')]')[i].click() #element(s) # 表のヘッダーの相違でtrの序数が変わる if len(driver.find_elements_by_xpath('//table/thead')) > 0: j = 1 else: j = 3 link = None # 地域画面のリンク要素 # 通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') # 岡山 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: while len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]')) > 0: # 現在のハンドルを保存 before_handle = driver.current_window_handle driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']//a[1]').click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) # 詳細画面も独自形式 num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[1]/td').text) out_url(ws1, k, 2, driver.current_url, num) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//caption').text, num) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[2]/td').text, num) out_tel(ws1, k, 8, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div//tr[3]/td').text, num) # 地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() # ブラウザの戻る j += 1 k += num # 知財高裁 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) == 0: out_url(ws1, k, 2, driver.current_url, 1) output(ws1, k, 3, 'エラー', 1) output(ws1, k, 4, 'i=' + str(i), 1) k += 1 if len(driver.window_handles) > 1: before_handle = driver.current_window_handle # ハンドルを保存 driver.switch_to.window(driver.window_handles[1]) driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す # 通常ケース&松江 while link is not None: # リンク先がpdfの場合は遷移無し url = link.get_attribute('href') if url[len(url) - 4:] == '.pdf': # urlの末尾4文字が'.pdf' num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[2]').text) out_url(ws1, k, 2, driver.current_url, num) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a').text, num) output(ws1, k, 5, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[3]').text, num) output(ws1, k, 8, driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[5]').text, num) else: # 現在のハンドルを保存 before_handle = driver.current_window_handle link.click() # タブが2枚になっていたら、新規タブが開いているので、タブを切り替える if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) #大阪地裁・簡裁 if '住所:' in driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text: num = 1 out_url(ws1, k, 2, driver.current_url, 1) output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text, 1) #郵便番号欄に住所も含まれている strbuf = driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text l_str = strbuf.splitlines() yubin = l_str[0][6:] #「郵便番号:〒」を削除 add = l_str[1][3:] #「住所:」を削除 output(ws1, k, 4, yubin, num) output(ws1, k, 5, add, num) out_tel(ws1, k, 8, driver.find_element_by_xpath (\ '//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text, num) else: num = out_yubin(ws1, k, 4, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/dl[1]/dd').text) out_url(ws1, k, 2, driver.current_url, num) # Excel出力 try: output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-MainColum"]/div/h3').text, num) except: # 表上部の裁判所が存在しない場合はヘッダー部から編集 output(ws1, k, 3, driver.find_element_by_xpath \ ('//div[@id="VcArea-Header"]/div/h2').text, num) output(ws1, k, 5, driver.find_element_by_xpath (\ '//div[@id="VcArea-MainColum"]/div/dl[2]/dd').text, num) # 電話番号が存在しないケースあり(横浜地方裁判所) if len(driver.find_elements_by_xpath( \ '//div[@id="VcArea-MainColum"]/div/dl[3]/dd')) > 0: out_tel(ws1, k, 8, driver.find_element_by_xpath( \ '//div[@id="VcArea-MainColum"]/div/dl[3]/dd').text,num) # 地域一覧画面に戻る if len(driver.window_handles) > 1: driver.close() # 新規タブを閉じる driver.switch_to.window(before_handle) # 元のタブに戻す else: driver.back() # ブラウザの戻る j += 1 k += num # while文の次の条件を設定 # 通常ケース if len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]/a') # 松江 elif len(driver.find_elements_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a')) > 0: link = driver.find_element_by_xpath \ ('//div//tr[' + str(j) + ']/td[1]//a') else: link = None ws1.cells(k, 1).select() # 表示デモ用 # Excel保存 book_path = r'D:\SeleniumCodeChecker\ListCourt\裁判所所在地.xlsx' wb1.save(book_path) wb1.close() # Excel出力関数 def output(ws, row, col, str, num): #num:行数 for i in range(num): ws.cells(row + i, col).value = str #郵便番号出力 def out_yubin(ws, row, col, str): #改行で分割して配列(list)に保存 l_out = str.splitlines() #改行がない場合は「,(全角カンマ)」で分割 if len(l_out) == 1: l_out = str.split(',') for i in range(len(l_out)): ws.cells(row + i, col).value = l_out[i] return len(l_out) #電話番号出力 def out_tel(ws, row, col, str, num): #num:行数 #改行で分割して配列(list)に保存 l_out = str.splitlines() for i in range(num): for j in range(len(l_out)): k = col + 4*j #出力列番号 ws.cells(row + i, k).value = l_out[j] if j > 0: if j == 1: rng_copy = xw.Range(ws.cells(row + i, col + 1), \ ws.cells(row + i, col + 3)) rng_paste = xw.Range(ws.cells(row + i, k + 1), \ ws.cells(row + i, k + 3)) rng_copy.copy(rng_paste) #rng_copyをrng_pasteにコピー #URL出力 def out_url(ws, row, col, str, num): for i in range(num): ws.cells(row + i, col).formula = '=HYPERLINK("' + str + '")' # main関数 if __name__ == "__main__": main()
スクリプトの実行
Excelテンプレート
Excelテンプレート
修正したExcelテンプレートで、再びスクリプトを実行します。
ディスカッション
コメント一覧
まだ、コメントがありません