SeleniumなしでWebDriverを操作するには - Part2
SeleniumなしでWebDriverを操作するには
はじめに
ブラウザで表示されているエレメントを操作するには
WebDriverでブラウザのエレメントを操作する場合はエレメント特有のIDが必要です。
特定のエレメントIDを取得する場合は以下に示されるエレメントの特徴をPOSTで渡すことが重要になります。
using | keyword |
---|---|
CSS selector | css selector |
Link text selector | link text |
Partial link text selector | partial link text |
Tag name | tag name |
XPath selector | xpath |
エレメントに関する基礎知識
CSS Selector
CSS(カスケーティングスタイルシート)で利用できる属性を指定します。
具体的には以下のようなHTMLがあるとき CSS Selector は [type="button"]
となります。
<input type="button" value="ココをクリック">
なお、WebDriverではvalue属性もCSS Selector として選択できる為
[value="ココをクリック"]
でも有効です。
Link text Selector
リンクテキスト、つまりはアンカータグに利用できるSelectorのことです。
aタグで括られている文字列を指定します。
Partial link text selector
Link text selector の部分文字列版
TagName
文字通りタグ名のこと
XPath selector
取得対象までのパスをスラッシュ区切りで書く。
これが一番とっつきにくそうでわかると一番やりやすい?かも
例:pタグを取得
/html/body/div/p
エレメントのプロパティとは
結論から語るとinnerHTML
や children
などのElement に関する情報が取得できる項目のこと
細かいことはMDN の Element のプロパティにありますので
具体的にエレメントとは何なのかは語りません。
とりあえず、エレメントはオブジェクトであるという認識で良いでしょう。
フレームという概念
昔のHTMLではframeとそれを束ねるframeset があり、比較的新しいHTMLについてはiframe(インラインフレーム)が使われます。
WebDriverではフレーム内のドキュメントを取得するとき、スイッチという動作を事前に行う必要があります。
ブラウザオートメーションで代表的なフレームワーク、Seleniumがわかる人であれば
SwitchToFrame
を実行すると言えばわかるかもしれない。
フレームにスイッチしてタグを取得
フレームは画面に描画されたタイミングでそれぞれ固有の番号みたいなものを持っており
基本的には左から0,1,2 と数えていけば良いです。
※Seleniumの場合はこのあたりのことを良しなに制御してくれているので意識する必要はないです。
WebDriverで同じことをやる場合はwindowにスイッチする時と同じ要領でやれば、簡単にできます。
エンドポイント:http://localhost:9515/session/{sessionId}/frame
メソッド:POST
リクエスト用のJSON※最初に描画されたframe を取得する場合
{
"id":0
}
スイッチしたらwindowにスイッチしなおすようにしましょう。
Windowにスイッチする方法はPart1で記載しております。
ちなみにこのスイッチ先のことをW3Cではコンテキストと表記しています。
コンテキストにスイッチすることでフレームを捉えることができるということですね。
※Selenium ではデフォルトコンテキストにスイッチすることで同じことができます。
エレメントを操作
エレメントIDを取り出すときのポイント
エレメントIDを取り出す時は定数値のキーを用いる必要があります。
具体的にはelement-6066-11e4-a52e-4f735466cecf
です。
エレメントを探す - CSS selector
エンドポイント:http://localhost:9515/session/{sessionId}/element
メソッド:POST
リクエスト用のJSON ※type 属性がbutton のとき
{
"using":"css selector",
"value":"[type=\"button\"]"
}
※ここで渡すvalueはSeleniumのfind_elements_by_css_selectorメソッドの引数と同じ
実行に成功した場合は以下のような形式で一番最初にヒットしたエレメントのIDをJSONで返します。
{
"value":
{
"element-6066-11e4-a52e-4f735466cecf": "{エレメントID}"
}
}
エレメントを探す - tag name
エンドポイント:http://localhost:9515/session/{sessionId}/element
メソッド:POST
リクエスト用のJSON ※取得したいタグ名がinputのとき
{
"using":"tag name",
"value":"input"
}
実行に成功した場合は以下のような形式で一番最初にヒットしたエレメントのIDをJSONで返します。
{
"value":
{
"element-6066-11e4-a52e-4f735466cecf": "{エレメントID}"
}
}
複数のエレメントを探す - CSS selector
FindElementと類似の機能にFindElements という機能があります。
FindElements は複数のエレメントIDを返します。
渡すデータやメソッドタイプに違いはありませんがエンドポイントが違うので利用時はエンドポイントを間違えないようにしましょう。
エンドポイント:http://localhost:9515/session/{sessionId}/elements
メソッド:POST
リクエスト用のJSON ※type 属性がbutton のとき
{
"using":"css selector",
"value":"[type=\"button\"]"
}
※ここで渡すvalueはSeleniumのfind_elements_by_css_selectorメソッドの引数と同じ
実行に成功した場合は以下のような形式で該当する全てののエレメントIDをJSONで返します。
{
"value": [
{
"element-6066-11e4-a52e-4f735466cecf": "エレメントID-1"
},
{
"element-6066-11e4-a52e-4f735466cecf": "エレメントID-2"
}
]
}
複数のエレメントを探す - tag name
エンドポイント:http://localhost:9515/session/{sessionId}/elements
メソッド:POST
リクエスト用のJSON ※取得したいタグ名がinputのとき
{
"using":"tag name",
"value":"input"
}
実行に成功した場合は以下のような形式で該当する全てののエレメントIDをJSONで返します。
{
"value": [
{
"element-6066-11e4-a52e-4f735466cecf": "エレメントID-1"
},
{
"element-6066-11e4-a52e-4f735466cecf": "エレメントID-2"
}
]
}
Find Element と Find Elements の違い
FindElement は最初にヒットしたエレメントのみを返しますが
FindElements は検索条件にヒットした全てのエレメントを配列で返します。
Find Elementの場合
{
"value": {
"element-6066-11e4-a52e-4f735466cecf": "0f1afb14-4601-4719-a2e1-9b1f322976a4"
}
}
Find Elementsの場合
{
"value": [
{
"element-6066-11e4-a52e-4f735466cecf": "0f1afb14-4601-4719-a2e1-9b1f322976a4"
},
{
"element-6066-11e4-a52e-4f735466cecf": "bd5e4f62-57a8-48c0-b457-997b5231784a"
}
]
}
画面上に一つしかないという要素であれば、FindElementで特定できますが
同じ要素が複数現れる場合は要素を限定してあげる必要があります。
後述しますが、WebDriverにはエレメントIDからエレメントの属性と属性値を調べる機能が存在します。
もし、確実に特定の要素だけをクリック/選択/コピーしたい場合はGet Element
系のメソッドと組み合わせることで
特定の要素を確実に操作するように調整できます。
このあたりは次のPart3 で語ります。
エレメントのプロパティを取得
エンドポイント:http://localhost:9515/session/{session id}/element/{element id}/property/{name}
メソッド:GET
エレメントが持つ項目を取得する時に利用します。
例えば、innerHTML
や children
がエレメントのプロパティに相当します。
pタグのエレメントIDを取得して以下のようなHTMLからinnerHTML
を取得する例
<html>
<head>
<title>test</title>
</head>
<body>
<p>innerHTML</p>
</body>
</html>
{
{"value": "innerHTML"}
}
エレメントの属性を取得
エンドポイント:http://localhost:9515/session/{session id}/element/{element id}/attribute/{name}
メソッド:GET
タグに付与されている属性値を取得します。
name 属性で属性値testの時のエンドポイントは
エンドポイント:http://localhost:9515/session/{session id}/element/{element id}/attribute/name
実行に成功した場合は指定した属性値ををJSONで返します。
{
"value": "test"
}
Webスクレイピングをするにあたっての基本
ここまで
WebDriverをウィンドウのコントロールやエレメントの操作まで解説してきましたが
Webスクレイピングの基本としては以下のような動作があります。
- 取得
- 要素の状態を取得
- ページソースを取得
- 入力
- UIクリック
- テキストを入力
- 出力
- ファイル出力
- ウィンドウ操作
- ウィンドウハンドルを取得
- ウィンドウタイトルを取得
- パース
- HTML
- XML
- JSON
- スクリプトの実行
- JavaScriptの同期実行
- JavaScriptの非同期実行
ここまでの内容とWebリクエストメソッドに関する知識だけでモダンブラウザを活用したWebスクレイピングが実現できます。
Part3 からは実際にプログラムを書いてWebDriverによるスクレイピングをやっていきます。
おわり
Part3 に続く
Discussion
とても勉強になりました!!
Part3 熱望しております!!
同上です。cookieの追加(add-cookie)、promptにテキスト送信(send-alert-text)の実装に躓いています。何卒。