RubyからIEを制御する
はじめに
一般的にはIEをRubyから制御する意味はあまりないかも。 ただ、会社で使うと便利なシーンがあるかもしれない。
ウチの会社のイントラネットはIEで利用するサービスがいくつかある。 それらのサービスをRubyからIEを制御して使うことで、いろんなことを半自動で入力 したり、登録してある情報をRubyで取り込んで、自分用に加工することができて、結構幸せ。
RubyからIEを制御する拡張ライブラリを作るのが目的なんだが、IEが持つ各オブジェクトの癖を理解しておかないと 使いこなせないと思うので、ちょっと解説をした後でライブラリを作ってみようと思う。
→「IE制御用ライブラリ」へ。
IE制御の基本
IE制御の基本は、以下のようになる。
- WIN32OLEでIE制御用のオブジェクトを作る(そのオブジェクトにはIEという名前をつけたとしましょう)
- IE.Navigateであるページを開く
- 開いたページのHTMLドキュメントを示すIE.DocumentオブジェクトをGet
- ほしい情報を持っているタグオブジェクトのコレクションをTagsメソッドで得る
- タグオブジェクトのコレクションから目的のタグオブジェクトを取得し、innerTextプロパティで問い合わせれば、 そのタグが持っている情報が手に入る
何かIEにアクションを起こさせたいなら、
- 入力関係のタグオブジェクト(INPUTタグなど)を取得し、そこに文字を書き込めば、文字を打ち込んだのと同じことになる
- リンクオブジェクトが手に入れて、Clickメソッドを作用させれば、リンクをクリックしたのと同じことになる
Googleで検索をかけてみる
基本ということで、Googleにキーワードを入れて、検索ボタンを押してみよう。
まずはさわりなので、キーワードの入力欄や検索ボタンの位置は決め打ちでやっている。よって、Googleのページのレイアウト が変わってしまえばもう動かなくなるが、まぁ、それはしかたあるまい。
require 'win32ole'
ie = WIN32OLE.new("InternetExplorer.Application") # (A)
ie.visible = true # (B)
ie.navigate("http://www.google.com/") # (C)
while ie.busy == true; sleep 0.5; end # (D)
OFFSET_KEYWORD = 0
OFFSET_SEARCH = 3
keyword_input = ie.document.body.all.tags("INPUT").item(OFFSET_KEYWORD) # (E)
search_button = ie.document.body.all.tags("INPUT").item(OFFSET_SEARCH)
keyword_input.value = "Ruby WIN32OLE" # (F)
search_button.click # (G)
解説。
- (A):ここでIE制御用のWIN32OLEオブジェクトを取得している。"InternetExplorer.Application"はIEを起動するオマジナイ。
- (B):IEの場合、起動時はウィンドウが不可視になっているので、見えるようにする。visibleはIEオブジェクトのプロパティ。 OLE経由で"visible=true"というメッセージがIEに届いて、IEの状態が変化する。すばらしい。
- (C):navigate()はIEのメソッド。URLを指定すれば、そのページを開く。これも"navigate()"というメッセージがOLE経由で IEに届いて、IEが動作する。
- (D): IEはnavigateでページを開くが、ページの描画か完了するまで待たされることはない。そのため、ページの描画が完了する まで待たせる必要がある。IEがBUSYの間はbusyプロパティがtrueになっているので、busyがfalseになるまで待っている。
- (E):Googleの場合、最初のINPUTタグオブジェクトが検索キーワードの入力欄になっている。ここではINPUTタグのコレクション の一番最初のINPUTタグオブジェクトをkeyword_inputが指すようにしている。その下のsearch_buttonは検索ボタンを指している。 このように、IE内部のオブジェクトを直接参照している(ように見える)オブジェクトを取得することが可能。
- (F):INPUTタグオブジェクトのvalueプロパティを使って、キーワードを入力している。ここを実行すると、IE上のキーワード欄 にここで指定したキーワードが設定される。
- (G):INPUTタグオブジェクトのclickメソッドを使うと、ボタンをクリックしたことになる。ここで、IEはGoogleの検索結果を表示 する。
IEの各種オブジェクトとメソッド/プロパティの調べ方
これまでに、いくつものIE内部のオブジェクトやメソッドを紹介してきた。これらはどうやって調べたか。
IEのMSDN Libraryで調べた。 英語だが、オブジェクトの種類やメソッド/プロパティなどはここを見ないわからないと思う。なお、このページはIEで見ないと まともに表示できないと思う。
IE自体が持っているnavigateメソッドやvisibleプロパティがまとめて載っているページは見つけられなかった。これらはいろんな人 のWebページで見つけたもの。
IEのDocumentオブジェクトの使い方
IEであるページを表示させると、IEの中にはWebページの内容がダウンロードされることになる。これらの情報を引き出す方法を説明してみよう。
HTMLドキュメントそのもの。
HTMLのBodyタグの中身。フレームを使ってないページはこれでHTMLにアクセスできる。
表示しているページが複数のフレームから構成されている場合、これでフレームのコレクションが手に入る。 framesはコレクションを返すので、IE.Document.frames.lengthはフレームの数を、IE.Document.frames.item(n)はn番目のフレーム(n=0が 最初のフレーム)を示す。これはIE.Document.frames(n)と書くこともできる。ただし、以下のようには書けない。Arrayとは違うのだ。
frame_collection = ie.Document.frames target_frame = frame_collection[n] # NG target_frame = frame_collection.item(n) # OK
コレクションだからeachが使えるかと思ったのだが、なぜかIE.Document.frames.each{|frame|...} は使えない。
これがn番目のフレームのDocumentオブジェクト。そのフレーム内のHTMLドキュメントそのもの。 もちろん、bodyメソッドでBodyタグの中身になる。
タグエレメントの使い方
Document.bodyオブジェクトは、HTML文書のBodyタグ要素を保持している。この中には<a>〜</a>や<table>〜</table>や<img>〜</img>などのタグ要素が いくつも存在している。 IE内部では、各タグ要素が独立したオブジェクトになっていて、そのタグ要素オブジェクトが持つプロパティで問い合わせれば、タグ要素が持つ いろんな情報を得ることができる。
いちいち「タグ要素オブジェクト」というのも何なので、「タグエレメント」と書くことにしよう。
タグエレメントを得るには、まず、タグエレメントのコレクションを取得し、条件にあうタグエレメントを探しだす。
link_collection = ie.Document.body.all.tags("A")
table_collection = ie.Document.body.all.tags("TABLE")
IEのコレクションはitem(n)というメソッドを持っていて、何番目かわかっているなら、オフセットnを指定して目的のタグエレメントを取り出すことができる。 最初の要素のオフセットは0である。
link_collection = ie.Document.body.all.tags("A")
target_link = link_collection.item(n)
ちなみに、コレクションの要素数はlengthというプロパティで参照できる。
IEのコレクションはWIN32OLEによって、eachメソッドによるイテレータが使えるようになっている。これを使えば、目的のタグエレメントを探すのは簡単だ。
たいていのタグエレメントにはinnerTextというプロパティがある。これは文字列を囲むようなタグエレメントに用意されていて、囲んだ部分の文字列を 返してくれる。 Yahooには乗り換え案内の「路線」リンクがあるので、これをクリックさせてみよう。クリックするには、clickメソッドを使う。
require 'win32ole'
ie = WIN32OLE.new("InternetExplorer.Application")
ie.visible = true
ie.navigate("http://www.yahoo.co.jp/")
while ie.busy == true; sleep 0.5; end
link_collection = ie.document.body.all.tags("A")
link_collection.each {|link|
if link.innerText == "路線"
link.click
end
}
IE制御用の拡張ライブラリを作ってみる
どんな機能があるとうれしいか。
- ページを表示し終わるまで待ってくれる
- 目的のタグを探し出してくれる
- ちょっと面倒なセレクタの選択をやってほしい
- 画像の取得
まぁ、この辺かな?
→「IE制御用ライブラリ」へ。
戻る