20
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Python】seleniumで親要素/子要素を取得する

Last updated at Posted at 2023-02-02

初めに

Seleniumを使っていると、Webサイトによっては同名のクラス名やidなどが存在して思うようにデータが取れない場合があります。
FullXPATHで指定することもできますが、少しでもWebの要素が変わると全てのXPATHを書き直す必要が出てくるかもしれません。

ある要素を軸に階層移動出来れば楽になりそうだと思ったので、色々と調べてまとめました。

バージョン

  • selenium: v4.7.2

要素の取得

単一要素であればfind_element、複数の要素であればfind_elementsで取得できます。
取得した要素は、WebElement型になります(複数の場合はlist[WebElement])。

# 単一要素
elm = driber.find_element(By.CLASS_NAME, "class_name")
# 複数要素
plants = driver.find_elements(By.TAG_NAME, "li")
elm = plants[0]

このelmから階層移動することが出来ます。

親要素の取得

現在のWebElementelmという名前で、そこから1階層だけ上に行きたい場合は、下記のように書きます

elm.find_element(By.XPATH, "..")

2階層上に行きたい場合は、

elm.find_element(By.XPATH, "../..")

と書くだけです。

因みにWebElementparentを持っていますが、これは親階層ではなく、その要素が属するWebDriverインスタンスへの内部参照を返します(参照)

子要素の取得

XPATH以外

これはドキュメントを読めば分かります。軽く触れておきましょう。
HTMLが下記の構成だと仮定します。

<ol id="vegetables">
 <li class="potatoes"><li class="onions"><li class="tomatoes"><span>Tomato is a Vegetable</span></ol>
<ul id="fruits">
  <li class="bananas"><li class="apples"><li class="tomatoes"><span>Tomato is a Fruit</span></ul>

そして、<ul id="fruits">の子要素である<li class="tomatoes">を取得したい場合は下記のように書きます。

fruits = driver.find_element(By.ID, "fruits")
tomatoes = fruits.find_element(By.CLASS_NAME,"tomatoes")

WebElement属性のfind_elementは、その属性の子要素を探索してくれます。
→ 上記のように検索しても、子要素にはないvegetablestomatoesは取得されない。

XPATH

XPATHも基本的には同じですが、XPATHの中身が少し異なります。
今回はHTMLが下記の構成だと仮定します。

<ul id="foods">
  <li class="fruits" title="bananas"><li class="fruits" title="apples"><li class="fruits" title="tomatoes"><span>Tomato is a Fruit</span></ul>
<ul id="fruits">
  <li class="fruits" title="bananas"><li class="fruits" title="apples"><li class="fruits" title="tomatoes"><span>Tomato is a Fruit</span></ul>

<ul id="fruits">の方の<li class="fruits" title="bananas">を取得してみましょう。

まずはfruitsの要素にアクセスして、そこからtitle=bananasを指定して取得する方法を考えてみます。

seleniumでは、By.TITLEがないのでXPATHで書く必要が出てきます。
//li[@title="bananas"]
これを組み合わせると下記のように書けます。

fruits = driver.find_element(By.ID, "fruits")
bananas = fruits.find_element(By.XPATH, "//li[@title='bananas']")

しかし、このように書いても両方(foods, fruits)のbananasが取得されてしまいます。
これはXPATHの//に原因があり、この//はルートから検索されてしまいます。
WebElementで現在いる階層を指定しても、XPATHを書き間違えると思うような動作が出来ないので注意が必要です。

子の要素をXPATHで取得する際は、XPATHの前に.を書いてあげましょう。

bananas = fruits.find_element(By.XPATH, ".//li[@title='bananas']")

これでfruitstomatoes要素だけが取得出来ました。

終わりに

XPATHを扱うのであれば、XPATHの記法を学びましょう(自戒)

参考

20
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?