Python Selenium スクレイピング

【Python】Seleniumでiframe(インラインフレーム)にハマった話

この記事は約6分で読めます。

 

業務で自動化テストでseleniumでサイトをスクレイピングするプログラムを組んでいたのですが、chromeのデベロッパツールで要素を確認してXPATHをコピーしてSeleniumの引数で指定した際に「no such element: Unable to locate element」が出ていて原因が分からずハマったので原因と解決方法をメモしておきます。

 

iframe(インラインフレーム)とは

 

ちなみにハマったのはこのサイトです

http://www1.river.go.jp/cgi-bin/SrchSiteSui2.exe

 

サイトの方を確認してもらえば分かりますが、print(driver.page_source) でSeleniumが読み込んでいるソースを読み込むと以下のようなHTMLが読み込まれていました。

 

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<meta http-equiv="Content-Style-Type" content="text/css">
<title>水系単位の観測所一括検索</title>
</head>
<frameset rows="96, *, 35" frameborder="NO">
 <frame name="WSearch" id="WSearch" src="SrchSiteSui2.exe?MODE=1" scrolling="NO" marginwidth="1" marginheight="1" noresize="">
 <frame name="SiteList" id="SiteList" src="SrchSiteSui2.exe?MODE=2" scrolling="YES" marginwidth="1" marginheight="1">
 <frame name="TSearch" id="TSearch" src="SrchSiteSui2.exe?MODE=3" scrolling="NO" marginwidth="1" marginheight="1" noresize="">
 <noframes>
  <BODY>
  <P>このページを表示するには、フレームをサポートしているブラウザが必要です。</P>
  </BODY>
  </noframes>
</frameset>
<font size="1">
</font></html>

 

どうやらこのページは古いサイトでインラインフレームが使われていたのが原因でした。要はこのインラインフレームというのはiframeタグでサイトのHTMLを分割していてxpathやcssがフレームごとに完全に独立しています。なのでseleniumでそのままデベロッパツールに表示されているxpathをコピーしてdriver.find_elements~をしてもその要素にアクセスすることができません。

 

フレームの確認

 

ウェブサイト内のフレームはBeautifulSoupを使えば以下のようにして確認できます。

 

~~~~
driver.get(対象サイトのurl)

from bs4 import BeautifulSoup

soup = BeautifulSoup(driver.page_source)

print(soup.find_all('frame')) # もしくはsoup.find_all('iframe')

 

 

スポンサーリンク
スポンサーリンク

Seleniumでiframe内の要素にアクセスする

 

Seleniumでこういったインラインフレームで作られているサイトをスクレイピングする際は

 

<iframe>タグのname=で指定されているフレーム名を指定して以下のメソッドで都度フレームを切り替える必要があります。

 

# frameを切り替える(frame名はページ内のframeタグのname属性を指定)
driver.switch_to.frame('フレーム名①')

 

対象のフレームにnameタグやidタグがない場合は以下のようにして確認&フレーム移動することも可能です。

 

# サイトの上から2番目のframeを選択して移動する
iframe = driver.find_elements_by_tag_name('iframe')[1]

driver.switch_to.frame(iframe)

 

他のフレームの指定方法(css_selectorやid指定など)については下記参照してください

参照:https://www.selenium.dev/ja/documentation/webdriver/browser/frames/

 

ちなみにこの処理はSeleniumの古いバージョンだとswitch_to_frame というメソッドになっているのでそれで実行すると以下のようなエラーになってしまうので注意です。

 

Message='WebDriver' object has no attribute 'switch_to_frame'

 

またサイト内にフレームが複数あって切り替える場合は特定のフレーム内にいる状態から別のフレームの要素は見れないので、no such a element になってしまいます。なので以下のメソッドでデフォルトの要素に戻る必要があります。

 

# デフォルトのフレームに戻る
driver.switch_to.default_content()

# 別のフレームに切り替える
driver.switch_to.frame('フレーム名②')

 

Seleniumのスクレイピングはまだまだ奥が深いです・・・

 

参考:https://stackoverflow.com/questions/70197944/webdriver-object-has-no-attribute-switch-to-frame

 

 


プログラミング・スクレイピングツール作成の相談を受け付けています!

クラウドワークス・ココナラ・MENTAなどでPython・SQL・GASなどのプログラミングに関する相談やツール作成などを承っております!

過去の案件事例:

  • Twitter・インスタグラムの自動化ツール作成
  • ウェブサイトのスクレイピングサポート
  • ダッシュボード・サイト作成
  • データエンジニア転職相談

これまでの案件例を見る

キャリア相談もお気軽に!文系学部卒からエンジニア・データサイエンティストへの転職経験をもとに、未経験者がどう進むべきかのアドバイスを提供します。


スポンサーリンク
/* プログラミング速報関連記事一覧表示 */
ミナピピンの研究室

コメント

  1. […] 関連記事:【Python】Seleniumでiframe(インラインフレーム)にハマった話 […]

タイトルとURLをコピーしました