【VBA×Selenium】iframe内の要素が取得できない時の対処法

みなさんこんにちは。

VBA×SeleniumでWebスクレイピングをしていると、デベロッパーツールでは対象の要素を確認できているにもかかわらず、VBAから要素を取得できないことがあります。

XPathやidの指定も間違っていないはずなのに「Element not found」などのエラーになってしまう場合、対象の要素がiframe内に存在している可能性があります。

今回は、iframe内にある要素をVBA×Seleniumで取得する方法についてご紹介したいと思います。

この記事はこんな人におすすめ

この記事はこんな人におすすめです!

  • VBA×Selenium:初学者~初級者
  • Webスクレイピングで要素を取得できず困っている人
  • XPathやidは合っているのにElement not foundになる人
  • iframe内の要素を操作したい人
  • コードだけサクッと取得したい人

といったところでしょうか。

VBA×Seleniumに関する過去の記事

VBA×Seleniumについては過去の記事でもご紹介しておりますので、そちらもどうぞ。

iframeとは

iframeとは、Webページの中に別のHTMLページを表示するための仕組みです。

例えば、HTMLが以下のようになっている場合です。

<iframe id="sampleFrame" name="sampleFrame" src="sample.html"></iframe>

画面上では一つのWebページに見えますが、Seleniumから見ると通常のページとiframe内では操作対象となる場所が異なります。

iframe内に検索ボタンが存在していることをChromeデベロッパーツールで確認した画面

上記の画面では、「検索する」ボタンが通常のWebページ上に表示されているように見えますが、デベロッパーツールで確認すると、sampleFrameというiframeの中にbtnSearchというボタンが存在していることが確認できます。

そのため、iframe内にある要素を直接取得しようとしても、対象の要素を見つけることができません。

よくある現象

例えば以下のようなコードでボタンを取得しようとします。

driver.FindElementById("btnSearch").Click

デベロッパーツールでは「btnSearch」というidを持つ要素が存在しているにもかかわらず、実行すると要素を取得できない場合があります。

VBA Seleniumでiframe内の要素を取得できずNoSuchElementErrorが発生した画面

この時、対象要素の上位階層を確認し、iframeタグの中に入っていないか確認してください。

対処方法

iframe内の要素を操作する場合は、先にSeleniumの操作対象をiframeへ切り替えます。

SeleniumBasicでは、以下のようにSwitchToFrameを使用します。

driver.SwitchToFrame "sampleFrame"

iframeへ切り替えた後であれば、その中にある要素を通常通り取得できます。

driver.SwitchToFrame "sampleFrame"

driver.FindElementById("btnSearch").Click

たったこれだけです。

iframeを使用しているWebページの場合は、要素を取得する前に操作対象となるフレームを切り替える必要があります。

コードの紹介

一連の処理を記述すると以下のようになります。

Sub main()

    Dim driver As New Selenium.ChromeDriver

    'Chrome起動
    driver.Start "chrome"

    'Webページを開く
    driver.Get "https://example.com"

    'iframeへ切り替える
    driver.SwitchToFrame "sampleFrame"

    'iframe内の要素をクリック
    driver.FindElementById("btnSearch").Click

    '元のページへ戻る
    driver.SwitchToDefaultContent

End Sub
VBA Seleniumでiframe内のボタンを正常にクリックできた画面

上記のコードを実行すると、iframe内の「検索する」ボタンを正常にクリックすることができます。
iframeへ切り替えてから要素を取得することで、先ほど発生していたNoSuchElementErrorも発生しなくなります。

コード解説

iframeへ切り替える

driver.SwitchToFrame "sampleFrame"

SwitchToFrameを使用して操作対象をiframeへ切り替えます。

上記ではiframeのnameとして「sampleFrame」を指定しています。

SeleniumBasicのSwitchToFrameでは、フレームの名前やインデックス、WebElementを指定して切り替えることができます。

iframe内の要素を取得する

driver.FindElementById("btnSearch").Click

フレームを切り替えた後は、通常通りFindElementByIdやFindElementByXPathなどを使用できます。

元のページへ戻る

driver.SwitchToDefaultContent

iframe内の操作が終わった後に、元のページにある要素を操作したい場合はSwitchToDefaultContentを使用します。

これを忘れると、今度は元のページに存在する要素を取得できなくなるので注意してください。

iframeをWebElementで指定する方法

iframeのidやnameを直接指定せず、iframe自体をWebElementとして取得してから切り替えることもできます。

Dim frameElement As Selenium.WebElement

Set frameElement = driver.FindElementByXPath("//iframe[@id='sampleFrame']")

driver.SwitchToFrame frameElement

iframeの特定方法が複雑な場合は、こちらの方法を使用しても良いかと思います。

注意点

iframeがあるからといって、要素を取得できない原因が必ずiframeとは限りません。

ページの読み込みが完了していない場合や、XPathの指定が間違っている場合でも同じように要素を取得できないことがあります。

そのため、要素を取得できない場合は以下の順番で確認すると原因を切り分けやすいかと思います。

  1. 対象要素のXPathやidが正しいか確認する
  2. ページの読み込みが完了しているか確認する
  3. 対象要素がiframe内に存在していないか確認する
  4. iframe内の場合はSwitchToFrameで切り替えてから取得する

Webページによってはiframeの中にさらにiframeが存在することもあります。

その場合は、外側のiframeから順番にSwitchToFrameを実行して操作対象を切り替えてください。

最後に

いかがでしたでしょうか。

今回は、VBA×Seleniumでiframe内の要素が取得できない時の対処法についてご紹介しました。

デベロッパーツールでは要素が見えているのにSeleniumから取得できない場合、原因を探すのに時間がかかることがあります。

そんな時は対象の要素がiframe内に存在していないか確認してみてください。

SwitchToFrameとSwitchToDefaultContentを覚えておけば、iframeを使用しているサイトでも対応できるようになります。

少しでもご参考になれば幸いです。

開発依頼について

ココナラでWebスクレイピング開発サービスを出品しております。

自分で開発をしようと思ったけど、VBAでのネット記事が少なく困っている方も多いかと思います。

そんな方はいつでもお気軽にご相談ください。

また、本ブログからご依頼いただいた方については割引特典がございますので、

ご不明点と合わせてメッセージをいただけると幸いです。

スモールスケールのWebアプリ開発します 先ずはスモールスケールのWebアプリから始めませんか?

Webスクレイピング以外にもWebアプリの開発サービスも出品しております。

こちらについても、本ブログからご依頼いただいた方については割引特典がございますので、

お気軽にご相談ください。

Excelにてブラウザ操作自動化ツールを作成します その作業、webスクレイピングを使って自動化しましょう!

ご興味がある方はこちら!!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA