【Python】Seleniumのfind_elementの使い方 結局CSS_SELECTOR一本でいい

Seleniumのfind_elementの使い方

Seleniumで一番よく使うのが、要素を探すfind_elementfind_elementsですよね、ブラウザを自動操作するときは、画面上のボタンや入力欄を「どうやって特定するか」がそのまま安定度に効いてきます

この記事はfind_element の使い方=「Byの選び方」と「エラーの回避」が主役です、CSSセレクタの書き方そのもの(属性・結合子・nth-childなどの一覧)は別記事「CSSセレクタの書き方 自動化で要素を狙う指定方法」にまとめたので、書き方を深掘りしたいときはそちらをどうぞ

目次

まずは要素検索の基本

まずはよくある基本の書き方です

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

driver = webdriver.Chrome()
driver.get("https://example.com")

element = driver.find_element(By.ID, "username")

このようにBy.IDBy.NAMEなどを使って要素を探します、1件だけならfind_element、当てはまる要素を全部リストで取りたいときはfind_elementsです

でも、このByの選び方によって、コードの安定性や書きやすさが全然変わってきます

Byの種類とそれぞれの特徴

Byの種類は実は結構な数がありまして、こんな感じです

  • By.ID
  • By.NAME
  • By.CLASS_NAME
  • By.TAG_NAME
  • By.LINK_TEXT
  • By.PARTIAL_LINK_TEXT
  • By.CSS_SELECTOR
  • By.XPATH

ネットでは By.ID や By.CLASS_NAME もよく見かけますが、結論は By.CSS_SELECTOR を使っておけば間違いないです

もう一つの候補が By.XPATH ですが、CSS_SELECTORはスクレイピングで使うBeautiful Soupにも応用できますし、記述がすっきりしてわかりやすいので、こちらに軍配が上がります

結局CSS_SELECTOR一本でいい理由

CSS_SELECTORが最適な一番の理由は、他のByを全部CSS_SELECTORで代用できるところにあります

つまり、CSS_SELECTORさえ覚えてしまえば、他を使う必要がなくなるんです

ここからは、各Byを CSS_SELECTOR に書き換えるとどうなるかの一覧です、find_element(By.◯◯, ‘値’) の◯◯と値が、CSS_SELECTORならこう書けます(XPATHも参考に並べました)

スクロールできます
探したいもの普通のBy指定CSS_SELECTOR一本だとXPATH(参考)
idBy.ID, ‘hoge’‘#hoge’‘//*[@id=”hoge”]’
classBy.CLASS_NAME, ‘hoge’‘.hoge’‘//*[@class=”hoge”]’
タグBy.TAG_NAME, ‘div’‘div’‘//div’
name属性By.NAME, ‘hoge’‘[name=”hoge”]’‘//*[@name=”hoge”]’
その他の属性専用のByなし‘[data-test=”hoge”]’‘//*[@data-test=”hoge”]’
複数クラス専用のByなし‘div.hoge.piyo’‘//div[contains(@class,”hoge”) and contains(@class,”piyo”)]’

ひとつ例外があって、リンクを文字(テキスト)で探す By.LINK_TEXT / By.PARTIAL_LINK_TEXT だけは、CSS_SELECTORに「文字で探す」書き方がありません、その場合は aタグを集めて for でテキスト一致させると同じことができます

# テキストが完全一致するリンク(By.LINK_TEXT 相当)
next((a for a in driver.find_elements(By.CSS_SELECTOR, 'a') if a.text == 'hoge'), None)

# テキストが部分一致するリンク(By.PARTIAL_LINK_TEXT 相当)
next((a for a in driver.find_elements(By.CSS_SELECTOR, 'a') if 'hoge' in a.text), None)

親子・兄弟もCSS_SELECTORでたどれる

CSS_SELECTORのもう一つの大きな強みが、親子要素・兄弟要素をたどって一意に指定できるところです

親子・兄弟というのは、HTMLソースで見たときの縦・横の関係です

  • 親子 … 階層の深さ(入れ子の関係)
  • 兄弟 … 同じ階層での横並び
親要素・子要素・兄弟要素の階層を示したHTML構造の図

例えば上の図で黄色く囲った説明文2ですの要素を取りたいとき、クラス名だけで指定すると

driver.find_element(By.CLASS_NAME, "description")

上にある「説明文です」の方を先に拾ってしまいます(n番目で指定する手もありますが、ややこしくなるので割愛します)

うまく取るには、指定が一意になるよう親要素からたどります、どこまで丁寧に書くかですが

  • ‘.younger .description’
  • ‘.younger > .card > .description’
  • ‘div.younger > div.card > p.description’

などで取れます

ここで使った スペース(子孫)や >(直下の子)といった結合子は、隣接(+)や兄弟(~)も含めて種類があります、結合子の一覧と使い分けは別記事「CSSセレクタの書き方」の結合子の節にまとめたので、引き出しを増やしたいときはどうぞ

※このページの下部に同じ画像とサンプルHTMLを置いてあるので、実際に試してみてください

開発者ツールでセレクタを下書きする

慣れればソースを見て起点の要素と狙った要素までの道のりが判断できるようになりますが、最初のうちは開発者ツール(DevTools)に下書きさせると早いです

開発者ツールでCSSセレクタをコピーする画面

右クリックのCopy → Copy selectorでセレクタを取得できます、ただそのまま使うには長くて壊れやすいことも多いので、下書きとして受け取って自分で短く整えるのがおすすめです

find_elementでよくあるエラーと回避方法

Seleniumを触っているとよく出会うのが NoSuchElementExceptionElementNotInteractableException です

要素が見つからなかったり、まだ読み込みが終わっていないのが原因です

例えば画面の文字を取得するとき、素直に書くとこうなりますが

一般的な文字の取得方法
hoge = driver.find_element(By.CSS_SELECTOR, '#hoge').text

ただ、これだと指定した要素が見つからなかったときにエラーで止まってしまいます

それを防ぐには、次の2パターンのどちらかがおすすめです

WebDriverWaitで要素の出現を待つ
# 10秒待っても要素が見つからないエラーをキャッチする
try:
    elm = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#hoge')))
    hoge = elm.text
except TimeoutException:
    print('#hoge が見つかりませんでした')
except Exception:
    print('予期せぬエラーが発生しました')
ジェネレータ式で最初の要素を取得する
# 要素が見つからないとNoneを返す
elm = next((e for e in driver.find_elements(By.CSS_SELECTOR, '#hoge')), None)
if elm:
    hoge = elm.text
else:
    print('#hoge が見つかりませんでした')

やり方は違いますが、どちらも「まず要素を検索」してから「目的のアクションを実行」することでエラーを防いでいます

このやり方なら、文字の取得だけでなく、文字入力やクリックにもそのまま流用できます

1つ目の WebDriverWait は奥が深くて、何を待つか(expected_conditions)の選び方で安定感が変わります、待ちでつまづいたら別記事「Seleniumで要素を確実に待つ方法」に詳しくまとめたので、あわせてどうぞ

あとがき

基礎の基礎に見える find_element でも、Byの選び方やエラー回避まで含めると結構奥が深いです

少しずつ理解を深めて、Seleniumを活用していきたいですね

あわせて読みたい記事も置いておきます

最後に、練習に使えるHTMLを置いておきますので、ご自由にどうぞ

サンプルHTML

下のサンプルはこのページに実際に表示されています、開発者ツールで構造を見ながら、上で紹介したセレクタを試してみてください

練習用サンプル

親要素です

子要素です

孫要素です

説明文です

詳しく見る

子要素の兄弟要素です

説明文2です

詳しく見る
📚 Python自動化の独学に効く本PR
退屈なことはPythonにやらせよう 第3版

退屈なことはPythonにやらせよう 第3版

Al Sweigart

Pythonクローリング&スクレイピング 増補改訂版

Pythonクローリング&スクレイピング 増補改訂版

加藤耕太

シゴトがはかどる Python自動処理の教科書

シゴトがはかどる Python自動処理の教科書

クジラ飛行机

私のおすすめからランダムで3冊を表示しています


最後に・・・

クラウドワークスココナラでお仕事受け付けています!

PythonとExcelを中心に仕事に役立つ業務ツールや自動化、スクレイピングツールの作成を受注していて、クラウドワークスでは気が付けば100件以上のお仕事を受注してきました!

会社員をやりながらの副業なので時間の捻出は相応ですが、クライアントの方々と近い立場でこちらからも提案しながら活動していますのでお悩みあれば是非ご相談ください

ココナラのプロフィールページへ

"ココナラ"に新規登録する際は1,000Pもらえる紹介コード使ってください

78E62K

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

VBAとPythonを中心にユーザー側でできるITを自己学習しているので備忘録半分、学習履歴を残して同じ道を辿る人の参考になればとブログを始めました

副業でスクレイピングツール作成を中心にできることを色々やっていますのでご相談いただけるとありがたいです!


クラウドワークスのページへ


ココナラのページへ

コメント

コメントする

目次