IPAT対応 投票支援ソフト作成への道

IPAT用の投票支援ソフトを作成したときのノウハウについてまとめてみました。

■インターネットエクスプローラを起動する

ウェブの画面を制御するためには、インターネットエクスプローラを起動して制御するのが手っ取り早いと思って、 ここを参考にして
テストしてみました。

(1) IPATの自動ログインから残高確認まで

VBでテスト用のフォームを作成、ボタンを1つ配置して、そのボタンで自動ログインから残高確認画面の表示までを
自動で実行する処理を作成してみました。

@ インターネットエクスプローラでIPATのログイン画面が完全に表示されたのを確認後、INET−IDをセットしてから
"ログインする"ボタンを自動クリックしてログインする。
A IPAT投票メインメニュー画面が完全に表示されたのを確認後、"照会メニュー"ボタンを自動クリックする。
B IPAT照会ログイン画面が完全に表示されたのを確認後、加入者登録番号、暗証番号、P-ARS番号をセットしてから
"OK"ボタンを自動クリックする。
C IPAT照会メニュー画面が完全に表示されたのを確認後、"残高確認"ボタンを自動クリックする。

大まかな手順としては、上の@〜Cまでなのですが、実際に制御してみると少し問題が発生しました。
それは、画面が完全に表示された事を確認する方法です。ボタンをクリックした後のページ表示チェックは、
http://www.ken3.org/vba/backno/vba156.html を参考にしてチェックする事は出来たのですが、
DocumentオブジェクトのallコレクションでItemの情報を取得した時に、タイミングによっては正常に取得出来ない場合がある事です。
そこでもう少しサイトで情報を探してみると見事にありました。

http://www.ken3.org/vba/backno/vba175.html

今までは、IEオブジェクトのBusyフラグでページが表示されたかチェックしていたのですが、それでは不完全だったようで、
ReadyStateフラグがREADYSTATE_COMPLETEになるのを待たないといけなかったようです。
とりあえず目標の残高確認画面の自動表示までは、何とか出来ました。

(2) インターネットエクスプローラを直接起動する問題点

インターネットエクスプローラを直接起動して制御を実行した時、終了時にVisibleフラグをFalseにしないと
インターネットエクスプローラの画面がそのまま残ってしまいます。
制御アプリを再実行すると別のインターネットエクスプローラが起動されてどんどん画面が増えてしまい、
ここで問題になるのが画面の表示チェックを実行する時に同じウィンドウタイトルの画面がすでに存在してしまって
チェックにならない事です。
そこで制御アプリの終了時に、VisibleフラグをFalseにしてみたのですが目標である画面が表示されたと同時に消えてしまうので
使いものになりません。
制御アプリの起動時に、IPAT関係の画面を全部閉じてから実行するようにもしてみたのですが、何か動きがバタバタしてしまって
落ち着きません。
投票データを自動入力後の実際の投票操作は手動でやるつもりなので、投票画面が表示されていた方が良いけど、目が疲れそうです。


■WebBrowserコントロール

VBの参照設定から、Microsoft Internet Controlsを選択してWebBrowserコントロールでテストしてみました。
インターネットエクスプローラを起動して制御したのと同様に、IPATの自動ログインから残高確認までの操作を
自動化してみましたが、またまたここで問題発生です。
INET−IDをセットしてから"ログインする"ボタンを自動クリックすると、勝手にインターネットエクスプローラの画面が開いてしまいます。
今回は、WebBrowserコントロールでテストしているのにどうやって制御すれば...と思って再び情報を探したところ、
NewWindow2イベントを制御すれば何とかなりそうな様子です。
マイクロソフトの参考ページを見てみると、どうやら新しいウィンドウが作成されるタイミングでイベントが発生するようです。

(1) テスト1(BeforeNavigate2を使用する方法 --> 動作NG)

まず最初にテスト用のフォームを用意してWebBrowser1、WebBrowser2の2つのWebBrowserコントロールをセットします。
WebBrowser1は、見やすい適当な大きさにフォームに配置してVisibleフラグをTrueにします。
WebBrowser2は、動作時にフォームに表示しないので小さく配置してVisibleフラグをFalseにしておきます。
デフォルトで使用するコントロールは、WebBrowser1としてWebBrowser1のNewWindow2、BeforeNavigate2イベント処理を追加して
新しいウィンドウが表示された時にデフォルトのWebBrowser1にそのまま表示するようにしてみます。


Private pbNewFlag As Boolean             ' 新規Window処理中を判定するフラグ

Private Sub WebBrowser1_NewWindow2(index as Integer, ppDisp As Object, Cancel As Boolean)

    Set ppDisp = Me.WebBrowser2.object   ' WebBrowser1のIDispatchインターフェースへのポインタに、
                                         ' 2番目のWebBrowserコントロールのオブジェクトをセットする
    pbNewFlag = True

End Sub

Private Sub WebBrowser1_BeforeNavigate2(index as Integer, ByVal pDisp As Object,
    URL As Variant, Flags As Variant, TargetFrameName As Variant, PostData As Variant,
    Headers As Variant, Cancel As Boolean)

    If pbNewFlag = True Then
        pbNewFlag = False
        Cancel =True                     ' Trueをセットして新しいWindowが開かれるのを抑止する

        ' 新規WindowをここでNavigateする
        Call Me.WebBrowser1.Navigate2(URL, Null, Null, Null, Null)
    End  If

End Sub

上記の処理は、単純に"_blank"で新しいウィンドウがOPENされる時は問題なく動作しました。
しかしIPATの場合は、BeforeNavigate2イベント処理のURLが"https://www.ipat.jra.go.jp/pw_020_i.cgi"となっていて???
正常に動作しませんでした。
CGIのしくみとかがほとんどわからなくて、単純に処理できないようなので、ここで断念ですm(__)m

(2) テスト2(WebBrowserコントロールを配列化する方法 --> 動作OK)

テスト1と同じようにテスト用のフォームを用意してWebBrowser1(0)、WebBrowser1(1)を配列化してセットします。
WebBrowser1(0)は、見やすい適当な大きさにフォームに配置してVisibleフラグをTrueにします。
WebBrowser1(1)は、デフォルトでフォームに表示しないので小さく配置してVisibleフラグをFalseにしておきます。
デフォルトで使用するコントロールは、WebBrowser1(0)です。また、グローバルな変数に"WbIdx"という名前で
WebBrowserコントロールを参照する
インデックスを作成しておきます。"WbIdx"は、初期状態で0にしておきます。
新しいウィンドウが表示されようとした時のNewWindow2イベント処理でWebBrowserコントロールの参照インデックスを切り替えて、
なおかつフォームに表示されるWebBrowserコントロール自体を入れ替えてしまおうと言う事です。


Private WbIdx As Byte                    ' 配列化したWebBrowserコントロールの参照インデックス

Private Sub WebBrowser1_NewWindow2(index As Integer, ppDisp As Object, Cancel As Boolean)

    If index = 0 Then                    ' 参照インデックスを入れ替える
        WbIdx = 1
    Else
        WbIdx = 0
    End If

    Set ppDisp = Me.WebBrowser1(WbIdx).object    ' IDispatchインターフェースへのポインタに、
                                                 ' 入れ替えたWebBrowserコントロールのオブジェクトをセット

    Me.WebBrowser1(index).Visible = False    ' 表示中のWebBrowserコントロールを非表示にする
    Me.WebBrowser1(WbIdx).Visible = True     ' 入れ替えたWebBrowserコントロールを表示する

    ' 2番目のWebBrowserコントロールの配置をデフォルトのWebBrowserコントロールに合わせる
    Me.WebBrowser1(1).Left = Me.WebBrowser1(0).Left
    Me.WebBrowser1(1).Top = Me.WebBrowser1(0).Top
    Me.WebBrowser1(1).Width = Me.WebBrowser1(0).Width
    Me.WebBrowser1(1).Height = Me.WebBrowser1(0).Height

End Sub

何とか同じフォーム上で残高確認画面まで進む事が出来ました。
別画面が開かないのでWebBrowserコントロールの中で表示が切り替わっても何とか許せるのではないかと思うところまで来ました。
あとは、各ページを解析して処理を積み重ねるだけか...と思いつつ、本当は投票入力画面に一発で行きたいのが本音。

まだまだ先は遠い...つづく。


■WinInet DLLを使う

直接投票処理を実行するにはどうすれば良いか...DIY競馬プログラミング IPAT DLL編に答えがありました。
さっそく本を購入して、1ヶ月くらい四苦八苦を繰り返しながらログインから自動投票までのテスト処理が実現できました。
IPAT関連の投票支援ソフトは、多機能のすばらしいソフトが多数公開されているので、ここではIPAT投票処理の仕組みや
WinInetの細かい使い方等についてではなく、実際にどのようにテストやデバッグをしたかについて書きたいと思います。
IPATの仕組みについては、DIY競馬プログラミング IPAT DLL編を参考にしてください。

IPATの場合、トップページの情報は簡単に取得出来ますが、その先の情報を取得するためにはCGIプログラムにデータを
POSTしなければなりません。
トップページの取得方法は、猫でもわかるネットワークプログラミングを参考にしました。これからネットワークプログラミングを
やってみたいという人にはおすすめです。
トップページが取得できたら、一旦ファイルに保存しておきます。こうしておけばIPATが時間外の時でもデバッグ出来ます。

CGIにPOSTしているデータは、ネットワークツールを使ってモニタリングします。
使用したパケットモニタのツールは、横取り丸とInetSpyです。
その他にEtherealというキャプチャソフトも使用しましたが、使い勝手が良いので、横取り丸とInetSpyを主として使用しました。
ただし、IPATのほとんどのページはSSLで暗号化されているために直接パケットの中身をモニタリングする事は出来ません。
実際にPOSTしているデータをパケットモニタで取得するためには若干のテクニックが必要なのでここで紹介します。

@ 横取り丸とInetSpyをインストールする

 秀まるお氏のサイトからダウンロードしてインストールします。もちろんフリーです。

 横取り丸のページ http://hide.maruo.co.jp/software/ydm.html
 InetSpyのページ  http://hide.maruo.co.jp/software/inetspy.html

 宣伝ではありませんが、秀丸エディタは10年以上使用しています。仕事でプログラムを作成する時にもかなり使ってます。
 ちなみに、このサイトもほとんど秀丸エディタを使用して作成しました。

A インターネットエクスプローラを設定する

 ダイヤルアップ接続の時は、[ツール] --> [インターネット オプション] --> [接続] で 「ダイヤルしない」にチェックする。
 LANで接続している時は、LANの設定を無効にする。
 ([コントロールパネル] --> [ネットワーク接続] --> [ローカル エリア接続]を右クリックして[無効にする]を選択)

B HTMLソースを編集してSSLで暗号化していないページにPOSTするようにする

 CGIにPOSTする時の情報は、HTMLソースのFORMタグに記述されています。
 FORMタグのaction属性に指定されているのがCGIのURLで、このURLを自分のホームページ等のURLに
 エディタで書き換えてしまいます。これでPOSTするデータが横取り丸とInetSpyでモニタリングできるようになります。

 HTMLリファレンスに関しては、とほほのWWW入門に詳しい情報がありますので参考にして下さい。

C 編集したHTMLソースでPOSTしてみる

 まず最初に、横取り丸を起動します。タスクトレイに横取り丸のアイコンが常駐するので、右クリックしてInetSpyを起動します。
 InetSpyが起動されたら[ファイル] --> [ログ取り開始]をクリックしてログ取得を開始します。
 これでパケットモニタリングの準備が出来ました。あとは、ソースを編集したHTMLファイルをインターネットエクスプローラで
 起動後に、必要な内容を設定してフォームのサブミットボタンをクリックすればPOSTされます。
 この時にInetSpyの画面にPOSTした情報が表示されればOKです。あとは、InetSpyの画面で[ファイル] --> [ログ取り停止]を
 クリックした後に、見たいパケットの行をダブルクリックすれば変更したURLにPOSTされている内容が確認出来ます。

 この時の注意点ですが、実際にはインターネット接続をOFFにしていれば問題ないと思いますが、INET IDやパスワード等の
 設定情報は無関係なデータを設定してテストするという事です。もし設定ミス等でインターネット接続が有効になっていたりすると
 暗号化されていない情報がネット上に流れてしまいます。モデムの電話線やLANケーブルは抜いてテストする方がいいです。


CGIにPOSTしているデータが確認出来れば、同じ構成のデータをプログラムで作成して各CGIのURLにPOSTすれば
IPATの各画面の情報が取得出来るようになります。
しかし実際には、ファイルに保存したHTMLソースを穴があくほど眺めて、やっとの思いで投票と残高照会が
出来るようになったのが現実です(笑)
IPATは、内部の解析処理をJavaScriptにまかせている事が多く、HTMLソースとJavaScriptソースの両方を解析して
初めて処理が理解出来るという感じだからです。おかげでJavaScriptにだいぶ詳しくなりました(^^;

※ 2006年7月にDIY競馬プログラミング IPAT DLL編が発売されましたので、リンク先を変更しました。


■参考情報とリンク

DIY競馬プログラミング IPAT DLL編
猫でもわかるネットワークプログラミング
VBAによるTCP/IPプログラミング入門
とほほのWWW入門


Club Yannies 競馬耳寄り情報局 「競馬三昧」

DIY競馬プログラミングの著者、吉田章太郎氏のサイトです。自動投票ソフト「シンプルぱっと2」が公開されています。


TARGET Diffusion TARGET Diffusion

IPAT用投票ソフト BET Master が公開されています。







[メインページに戻る] Copyright (C) 2005 RAT