こんにちわ、ルーターエンジニアのMatsunagaです。

「この世に取得できない値はない」……..

ということで、今回はRubyを使ったスクレイピングでhtmlをパースする際、セレクタの指定で詰まった時に使う最終手段的な手法をご紹介します。 過去に弊社でも基本的なCSSセレクタに関する記事を公開しておりましたが、今回はその一歩先をご説明します。

要素指定で詰んだ・・・

ゴリゴリに動的なサイトをスクレイピングしていると稀に要素の指定が困難なケースに遭遇します。
例えば指定したい要素に、
・idがない
・特定のclassがない
・親要素に対して順番が動的に変化する
のような場合、どうやって指定するのかが問題になります。

特に最後の「親要素に対して順番が動的に変化する」が問題で、
どんな複雑な構造でも、静的なページであれば、

#u_6_c > div > div > div._5as1 > div > div > button:nth-child(2) > p

のような形でフルパスで指定してしまえば問題ないのですが、
構造が頻繁に変化する動的なページで、継続的にスクレイピングをする場合、この手は通用しません。

以下、そのような場合の対処法をご紹介します。

CSSセレクタで 属性の値で要素を検索する

特定できるidもclassもなく、順番も動的に変化するが、特定の属性値が存在する場合、CSSセレクタで以下の方法で指定が可能です。

・取得したいhtml要素

<button aria-label="指定しない1"></button>
<button aria-label="この要素を指定する"></button>
<button aria-label="指定しない2"></button>

・指定方法

@selenium.find_elements(:css, 'button[aria-label="この要素を指定する"]')

XPath でテキストの文字列で要素を検索する

特定できるidもclassもなく、順番も動的に変化する、かつ特定の属性値が存在しない場合、CSSセレクタでは要素の検索ができません。
しかしXPathを使えば、文字列で要素の指定をすることができます。
ただし、当然、指定要素のテキストが変化しないことを前提としています。

・取得したいhtml要素

<button >指定しない</button>
<button >この要素を指定する</button>
<button >指定しない</button>

・指定方法

@selenium.find_elements(:xpath, "//button[text()=\"この要素を指定する\"]")

まとめ

上記の方法を選択肢に加えれば、htmlの大抵の要素はパースできるのではないかと思います。
それでは、快適なスクレイピングライフをお送りください!