Python + Seleniumでframe内のテーブルを取得してエクセルに保存


はじめに

タイトル通り。
作業自動化のためスクレイピングの勉強中。

確認した環境

Pythonコード

'''
特定のサイトURLから、特定のテーブルデータを取得し
指定のエクセルファイルに保存する
'''
import os
# Excel用ライブラリ読込
import openpyxl
# ブラウザ用ライブラリ読込
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.event_firing_webdriver import EventFiringWebDriver
from selenium.webdriver.support.abstract_event_listener import AbstractEventListener

# Parameters
# webdriver path
webdriver_path = r'/path/to/chromedriver.exe'
# saving excel file path
excel_file_path = r'output.xlsx'
# web site path, info
# sample
access_site = r'https://seleniumhq.github.io/selenium/docs/api/java/index.html'
frame_name = 'classFrame'
table_class_name = 'overviewSummary'

class MyListener(AbstractEventListener):
    def before_navigate_to(self, url, driver):
        # URL遷移直前の処理
        print("before_navigate_to:" + driver.current_url)

    def after_navigate_to(self, url, driver):
        # URL遷移直後の処理
        print("after_navigate_to:" + driver.current_url)

# Excel Workbookオブジェクトを取得
if not os.path.exists(excel_file_path):
    v_wb = openpyxl.Workbook()
else:
    v_wb = openpyxl.load_workbook(excel_file_path)

# アクティブなシートを変数へ
v_ws = v_wb.active

# Chrome用ドライバー読込
options = Options()
# ヘッドレスで動作させる場合、以下をコメントアウト
# options.add_argument('--headless')
driver = webdriver.Chrome(executable_path=webdriver_path, options=options)
v_browser = EventFiringWebDriver(driver, MyListener())

try:
    v_browser.get(access_site)
    frames = v_browser.find_elements(By.TAG_NAME, 'frame')
    if frames:
        print('count of frames = ' + str(len(frames)))
    # frame_nameが定義されている場合、スイッチする
    if frame_name:
        target_frame = v_browser.find_element_by_name(frame_name)
        v_browser.switch_to.frame(target_frame)
    # Tableのclassを指定して取得(複数のTableが見つかる可能性がある場合はelementsにする)
    v_table = v_browser.find_element_by_class_name(table_class_name)
    trs = v_table.find_elements(By.TAG_NAME, 'tr')
    # Tableのheaderを取得
    list_header_line = []
    try:
        # v_table_thread = v_table.find_element(By.TAG_NAME, 'thead')
        ths = v_table.find_elements(By.TAG_NAME, 'th')
    except NoSuchElementException as nsExcep:
        print('NoSuchElementException occured')
        print(nsExcep)
        pass
    else:
        # ヘッダの値を取得
        for i in range(0, len(ths)):
            list_header_line.append(ths[i].text)

    # Tableのbodyを取得
    list_table = []
    for i in range(1, len(trs)):
        tds = trs[i].find_elements(By.TAG_NAME, 'td')
        line = ""
        list_line = []
        for j in range(0, len(tds)):
            list_line.append(tds[j].text)
        list_table.append(list_line)

    for list_line in list_table:
        print(list_line)

    # ヘッダを書き込み
    alphabet_count = 0
    for val in list_header_line:
        v_ws.cell(column=alphabet_count+1, row=1).value = val
        alphabet_count += 1
    # 2行目から、最大行+1まで繰り返す
    line_count = 2
    for list_line in list_table:
        alphabet_count = 0
        for val in list_line:
            v_ws.cell(column=alphabet_count+1, row=line_count).value = val
            alphabet_count += 1
        line_count += 1
finally:
    # ブラウザを閉じる
    driver.quit()

# Excelファイルを保存
v_wb.save(excel_file_path)

メモ

chromeは文字コードの指定方法が見つけられなかったため、文字化け対策できないように思えた。
文字化け対策には以下のようなBeautifulSoupの方法と組み合わせて取得したほうが良いかもしれない。
https://qiita.com/hujuu/items/b0339404b8b0460087f9

参考にしたサイト

https://qiita.com/memakura/items/20a02161fa7e18d8a693
https://www.seleniumqref.com/api/webdriver_gyaku.html
https://www.ex-it-blog.com/Python-Excel-fare
https://qiita.com/Azunyan1111/items/b161b998790b1db2ff7a