Categories: Python

【Python】Seleniumを使ってWebブラウザを自動化する

この記事では、Seleniumを使ってWebブラウザを自動化する方法を解説します。

Seleniumを使うことでWebブラウザでの操作を自動化することができます。例えば、Google検索して表示されたサイトのリンクやタイトルなどを抽出したりすることができます。

それでは、Seleniumの使い方を見ていきましょう!

インストール

Seleniumpipでインストールすることができます。

pip install selenium

セッションの開始と終了

最初にブラウザを開いたり閉じたりするためのセッションを作成します。セッションは、Driverオブジェクトを初期化することによって自動的に作成されます。

from selenium import webdriver

driver = webdriver.Chrome()

上記コードではChrome()を使ってセッションを作成しましたが、他にもSafari()Edge()Firefox()などのドライバーが用意されています。

driver = webdriver.Safari()
driver = webdriver.Edge()
driver = webdriver.Firefox()

エラーが発生してうまくいかない場合は以下のページを参考にしてください。

LinkUnable to Locate Driver Error | Selenium

ブラウザでの処理が終わったらセッションを終了しましょう。

driver.quit()

コンテキストマネージャーとして実行することもできます。

from selenium import webdriver

# セッションの開始(ドライバーの生成)
with webdriver.Chrome() as driver:
    # 何らかの処理

Webサイトを開く

任意のWebサイトを開くには、driver.get()メソッドを使います。

driver.get(url: str)

例えば、Googleを開くには以下のようにします。

from selenium import webdriver

# セッションの開始(ドライバーの生成)
driver = webdriver.Chrome()

# Webサイトを開く
driver.get("https://google.com/")

# セッションの終了
driver.quit()

ブラウザの操作・情報の取得

ブラウザから情報を取得したり、操作したりすることができます。

操作

開いたブラウザでは以下のような操作が可能です。

# 戻る
driver.back()

# 進む
driver.forward()

# 更新
driver.refresh()

情報の取得

以下のようなプロパティからブラウザの情報を取得できます。

# タイトルの取得
driver.title

# URLの取得
driver.current_url

ウィンドウとタブ

ドライバーはウィンドウとタブを区別しません。各ウィンドウにはユニークな識別子が付けられており、そのセッション内で永続的に保持されます。

識別子の取得

ドライバーのcurrent_window_handleから現在のウィンドウの識別子を取得できます。

window_handle = driver.current_window_handle

ウィンドウ・タブの切り替え

switch_to.window()の引数に表示したいウィンドウ、またはタブの識別子を指定することでその画面に切り替えることができます。

driver.switch_to.window(window_handle)

新しいウィンドウ、またはタブを作成して切り替える

new_window()を使うことで新しいウィンドウ、またはタブを作成し、その画面に切り替えることができます。

# 新しいウィンドウを作成し、そのウィンドウに切り替える
driver.switch_to.new_window('window')

# 新しいタブを作成し、そのタブに切り替える
driver.switch_to.new_window('tab')

ウィンドウ、またはタブを閉じる

ウィンドウ、タブはclose()で閉じることができます。

driver.close()

閉じたら元のウィンドウ、またはタブに切り替える必要がある。

from selenium import webdriver

# セッションの開始(ドライバーの生成)
with webdriver.Chrome() as driver:

    # Webサイトを開く
    driver.get("https://google.com/")

    # 元の画面の識別子を保存しておく
    window_handle = driver.current_window_handle

    # 新しいタブの作成し、切り替える
    driver.switch_to.new_window('tab')

    # タブを閉じる
    driver.close()

    # 元のタブに切り替える
    driver.switch_to.window(window_handle)

ウィンドウの管理

ウィンドウのサイズや位置を管理することができます。

ウィンドウサイズの取得

ブラウザウィンドウのサイズをピクセル単位で取得します。

d = driver.get_window_size()
print(d)
# {'width': 1200, 'height': 637}

辞書として返されるのでキーを指定することでそれぞれの値にアクセスできます。

width = driver.get_window_size()['width']

# dict.get() でより安全
width = driver.get_window_size().get("width")

ウィンドウサイズの設定

set_window_size()widthheightを指定することでウィンドウのサイズを変更できます。

driver.set_window_size(640, 480)

ウィンドウの位置の取得

get_window_position()でウィンドウの位置を取得できます。

pos = driver.get_window_position()
print(pos)
# {'x': 22, 'y': 47}

辞書として返されるのでキーを指定することでそれぞれの値にアクセスできます。

x = driver.get_window_position()['x']

# dict.get() でより安全
x = driver.get_window_position().get('x')

ウィンドウの位置の設定

get_window_position()で指定した位置にウィンドウを移動させることができます。

driver.set_window_position(0, 0)

ウィンドウの最大化

maximize_window()でウィンドウを最大化できます。

driver.maximize_window()

ウィンドウの最小化

minimize_window()でウィンドウを最小化できます。

driver.minimize_window()

全画面にする

fullscreen_window()でウィンドウを全画面にすることができます。

driver.fullscreen_window()

スクリーンショットを撮る

画面を Base64 形式でエンコードされたスクリーンショットでキャプチャすることができます。

driver.save_screenshot('image.png')

要素の検索

任意の要素を検索して取得することができます。

最初に一致した要素の取得

引数で指定した条件に一致した最初の要素を取得するにはfind_element()を使います。

def find_element(
    by: str = By.ID,
    value: str | None = None
) -> WebElement

by引数はselenium.webdriver.common.byByクラスでロケーターを指定します。例えば、以下のような感じです。

from selenium import webdriver
from selenium.webdriver.common.by import By

# by引数にはデフォルトで By.ID が渡されているので id="abc" の最初の要素
driver.find_element(value="abc")

# class="abc" の最初の要素
driver.find_element(By.CLASS_NAME, "abc")

# name="abc" の最初の要素
driver.find_element(By.NAME, "abc")

# h2タグの最初の要素
driver.find_element(By.TAG_NAME, "h2")

また、取得した要素からさらに検索することも可能です。例えば以下のコードでは、メインコンテンツ内のclass="abc"を検索します。

main = driver.find_element("main-contents")
abc = main.find_element(By.CLASS_NAME, "abc")

上記の方法だとfind_element()を2度実行しなければならないが、CSSやXPathを使って以下のように指定することで一度で取得することができます。

driver.find_element(By.CSS_SELECTOR,"#main-contents .abc")

一致するすべての要素の取得

指定した条件に一致した全ての要素を取得するにはfind_elements()を使います。

def find_elements(
    by: str = By.ID,
    value: str | None = None
) -> List[WebElement]

例えば、body内の全てのaタグを取得するには以下のようにします。

driver.find_elements(By.CSS_SELECTOR, "body a")

待機

Webページ上の要素はすぐに利用できるものばかりとは限りません。読み込みに時間がかかったり、JavaScriptの処理が終わらないと使えない要素もあります。

そのような要素を取得するには待機を使う必要があります。

明示的な待機

明示的な待機を実行するにはWebDriverWaitを使います。

from selenium.webdriver.support.wait import WebDriverWait

class WebDriverWait(
    driver: Any,
    timeout: float,
    poll_frequency: float = POLL_FREQUENCY,
    ignored_exceptions: WaitExcTypes | None = None
) -> None

条件はuntil()を繋げて指定します。

WebDriverWait(driver, timeout=10).until(条件)

指定された条件が解決するまで、プログラムの実行を停止したり、スレッドをフリーズしたりすることができます。この条件はtimeout引数に指定した秒数が経過するまで特定の頻度(poll_frequency引数の値、デフォルトは0.5秒)で呼び出され、条件がfalseを返す限り、試行と待機を繰り返します。

JavaScriptを同期実行し、ある変数の値がTrueになるまで待機するには以下のようにします。

WebDriverWait(driver, timeout=10).until(lambda d: d.execute_script("return 変数名"))

他にも任意のタグが取得できるまで待機したりできます。

p = WebDriverWait(driver, timeout=3).until(lambda d: d.find_element(By.TAG_NAME,"p"))

暗黙的な待機

暗黙的な待機を実行するにはドライバーのimplicitly_wait()を使います。

def implicitly_wait(time_to_wait: float) -> None

暗黙的な待機は一定期間DOMをポーリングします。Webページ上の特定の要素がすぐには利用できず、読み込みに時間がかかる場合に使います。

from selenium import webdriver
from selenium.webdriver.common.by import By

# セッションの開始(ドライバーの生成)
with webdriver.Chrome() as driver:

    # 暗黙的な待機
    driver.implicitly_wait(10)

    # Webサイトを開く
    driver.get("https://google.com/")

    # 要素の取得
    q = driver.find_element(By.NAME, "q")

アクションの実行

要素に対して様々なアクションを実行することができます。

クリック

要素をクリックするにはclick()を使います。

WebElement.click()

例えば、a要素をクリックして他のページを開いたりできます。

from selenium import webdriver
from selenium.webdriver.common.by import By

# セッションの開始(ドライバーの生成)
with webdriver.Chrome() as driver:

    # 暗黙的な待機
    driver.implicitly_wait(0.5)

    # Webサイトを開く
    driver.get("https://google.com/")
    driver.implicitly_wait(0.5)

    # 現在のURL
    print(driver.current_url)

    # a要素を取得し、クリックする
    a = driver.find_element(By.CLASS_NAME, "MV3Tnb")
    a.click()
    driver.implicitly_wait(0.5)

    # 現在のURL
    print(driver.current_url)

キーの送信

send_keys()を使うことで指定されたキーを編集可能な要素に入力することができます。テキストフィールドとコンテンツ編集可能な要素にのみ適用されます。

WebElement.send_keys(*value: Any)

例えば、適当なことをGoogleで検索してみます。

from selenium import webdriver
from selenium.webdriver.common.by import By

# セッションの開始(ドライバーの生成)
with webdriver.Chrome() as driver:

    # Webサイトを開く
    driver.get("https://google.com/")
    driver.implicitly_wait(0.5)
    
    # テキストエリアの取得
    textarea = driver.find_element(By.NAME, "q")
    driver.implicitly_wait(0.5)

    # テキストエリアに入力 
    textarea.send_keys("調べたいこと")
    driver.implicitly_wait(0.5)

    # 検索ボタンを検索してクリック
    button =  driver.find_element(By.NAME, "btnK")
    button.click()
    driver.implicitly_wait(0.5)

    # 検索結果のタイトルを出力
    for h3 in driver.find_elements(By.TAG_NAME, "h3"):
        print(h3.text)

上記では検索ボタンをクリックしましたが、Enterキーで検索することもできます。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

# セッションの開始(ドライバーの生成)
with webdriver.Chrome() as driver:

    # Webサイトを開く
    driver.get("https://google.com/")
    driver.implicitly_wait(0.5)
    
    # テキストエリアの取得
    textarea = driver.find_element(By.NAME, "q")
    driver.implicitly_wait(0.5)

    # テキストエリアに入力し、Enterキーを実行
    textarea.send_keys("調べたいこと", Keys.ENTER)
    driver.implicitly_wait(0.5)

    # 検索結果のタイトルを出力
    for h3 in driver.find_elements(By.TAG_NAME, "h3"):
        print(h3.text)

クリア

clear()を使うことで編集可能でリセット可能である要素の内容をクリアできます。

# テキストエリアの取得
textarea = driver.find_element(By.NAME, "q")
driver.implicitly_wait(0.5)

# テキストエリアに入力
textarea.send_keys("調べたいこと")
driver.implicitly_wait(0.5)

# テキストエリアをクリア
textarea.clear()

要素の情報の取得

要素から様々な情報を取得することができます。

from selenium import webdriver
from selenium.webdriver.common.by import By

# セッションの開始(ドライバーの生成)
with webdriver.Chrome() as driver:

    # Webサイトを開く
    driver.get("https://google.com/")
    driver.implicitly_wait(0.5)
    
    # イメージの取得
    img = driver.find_element(By.TAG_NAME, "img")
    driver.implicitly_wait(0.5)

    # 表示されているかどうか
    img.is_displayed()  # True

    # 有効かどうか
    img.is_enabled()    # True

    # 選択されているかどうか
    img.is_selected()   # False

    # タグ名
    img.tag_name        # img

    # サイズと位置
    img.rect            # {'height': 92, 'width': 272, 'x': 464, 'y': 60}

    # テキストコンテンツ
    img.text            # 

    # CSS値の取得
    img.value_of_css_property('height')  # 92px

    # 属性またはプロパティの取得
    img.get_attribute("alt")  # Google

まとめ

この記事では、Seleniumを使ってWebブラウザを自動化する方法を解説しました。

Seleniumを使うことでWebブラウザで行う操作をプログラムにやらせることができました。もしWebブラウザで定期的に行う処理がある場合は作業を自動化すると楽です。

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ

ゆうまる

独学でプログラミングを勉強しているおじさん。いろんな言語を勉強したが浅く広くなためあまり仕事につながらない。また忘れっぽいため自分のブログを備忘録としても使っている。産まれてこのかたずっとネコを飼ってる生粋のネコ派。最近お腹が出てきて筋トレに奮闘中!

Recent Posts

【Dart】コンストラクタのデフォルト引数について

Dartのコンストラクタのデフォルト引数…

2週間 ago

【Unity】有料アセットを無料で手に入れる方法

この記事では、Unityの有料アセットを…

4か月 ago

【Python】任意の秒数だけ処理を一時停止する方法【sleep()関数】

この記事では、Pythonで任意の秒数だ…

1年 ago

【Python】Wordの文書の新規作成と読み書き

この記事では、Pythonを使ってWor…

1年 ago

【Python】メタクラスって結局なんなの?

この記事では、Pythonのメタクラスに…

1年 ago