VBSでのIE操作(AngularJSのページ)でプルダウン選択が効かない
- 評価
- クリップ 0
- VIEW 1,922

退会済みユーザー
前提・実現したいこと
VBSでIE(11)を操作してスクレイピングするシステムを作っています。
IEで操作したいwebページが、Javascriptのフレームワークである
Angular(1.2)を利用したページでうまく動かない箇所がある為、解決策について相談させて下さい。
宜しくお願いいたします。
■スクレイピングしたいページ
プルダウンを選択して、ボタンを押すと
プルダウンで選択した値がメッセージとして表示されるページです。
(実際のページを見せるわけにはいかないので、簡易的なページで再現しています)
■サンプル
http://153.121.53.155/q/angular_test.html
発生している問題・エラーメッセージ
VBSのIE操作で、プルダウンを選択してもメッセージに反映されず
「undefinedを選択しました」と表示されてしまいます。
VBSでプルダウン選択・ボタンクリックはできているので
おそらくAngularの動きに原因があるのではと考えています。
VBSで操作したときのIEの挙動(動画):
http://153.121.53.155/q/2017-03-17_1655.swf
該当のソースコード
<?xml version="1.0" encoding="utf-8" ?>
<package>
<job>
<runtime></runtime>
<script language="VBScript">
<![CDATA[
Sub IEClose()
'IEを閉じる
Dim objProcess
Dim objProcList
Dim strProcName
strProcName = "iexplore.exe"
Set objProcList = GetObject("winmgmts:").InstancesOf("win32_process")
For Each objProcess In objProcList
If LCase(objProcess.Name) = strProcName Then
objProcess.Terminate
Exit For
End If
Next
Set objProcList = Nothing
End Sub
Sub waitPage(objIE)
'IEブラウザが開くまで待つ
WScript.sleep (300)
Do While objIE.busy
Loop
Do While objIE.Document.readyState <> "complete"
Loop
End Sub
Sub getPage(objIE, strURL)
'ページを取得する関数
objIE.Navigate (strURL)
Call waitPage(objIE)
End Sub
set objIE = WScript.CreateObject("InternetExplorer.Application")
objIE.Visible = True
Call getPage(objIE, "http://153.121.53.155/q/angular_test.html")
Call waitPage(objIE)
Set money_select = objIE.Document.getElementsByTagName("SELECT")(0)
money_select.selectedIndex = 2
money_select.fireEvent("onchange")
Call waitPage(objIE)
Set objBtn = objIE.Document.getElementsByTagName("button")
objBtn(0).click
Call waitPage(objIE)
]]>
</script>
</job>
</package>
試したこと
・だめもとで、プルダウンのoption要素に対しても、fireEventをつけてみたのですが挙動は変わらずでした。
Set money_option = objIE.Document.getElementsByTagName("OPTION")(2)
money_option.fireEvent("onchange")
補足情報(言語/FW/ツール等のバージョンなど)
VBS
・IE11を操作
スクレイピング先ページ ライブラリ
・AngularJS v1.2.26
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+1
ちょっと正確にはわからないのですが、ng-modelの発火イベントがスクリプト起動だと発生していないのかもしれませんね。
VBScriptの動作環境がないので東方で確認できないのですが、ng-optionsという機能がありますので利用してみては如何でしょうか。
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8"/>
<title>AngularJS テスト</title>
</head>
<body>
<form ng-controller="myController">
<label for="name">金額:</label>
<select id="name" name="name" ng-model="name" ng-options="name for name in names">
</select>
<button ng-click="onclick()">送信</button>
<div>{{msg}}</div>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<script>
angular.module('myApp',[]).controller(
'myController',
[
'$scope',
function($scope){
$scope.names=[1000,2000,3000]
$scope.msg='金額を選択して下さい';
$scope.onclick=function(){
$scope.msg=$scope.name+'を選択しました';
};
}
]
);
</script>
</body>
</html>
もしくはonclickの最初に$scope.apply();を実行してはどうでしょうか。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 90.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/03/22 16:45
いただいたアドバイスをもとに試してみたのですが
解決には至りませんでした。
>ng-optionsという機能がありますので利用してみては如何でしょうか。
私の説明が悪く申し訳ないのですが、スクレイピングしたいページ(Angular利用)はこちらから
編集する事ができないページの為、この対応は出来なさそうです。
>onclickの最初に$scope.apply();を実行してはどうでしょうか。
VBSでJavascriptを実行するPGMで、アドバイスいただいたやり方を試してみましたが
挙動に変化はなく、ダメでした。
※ボタンを押す前に、「$scope.$apply();」を実行してみました。
-------------
objIE.Document.Script.setTimeout "javascript:$scope.$apply();", 1000
Set objBtn = objIE.Document.getElementsByTagName("button")
objBtn(0).click
-------------
参考にしたサイト:
http://d.hatena.ne.jp/ken3memo/20110626/1309072974
2017/03/22 20:16
そうするとこの問題が解決可能かどうかの結論を得るためにはAngularJSに対する非常に深い知識が必要になってくると思われるのですが、私にはそこまでの知識がなく力になれそうにありません。
具体的にはAngularJSはどのようにページの変更イベントを受け取り$scopeを随時更新しているのか、そしてそれはVBScriptから動かしたときにどのように動作するのかということが説明できなければなりません。
私の知識は乏しいのですが、できるだけAngularJSネイティブな書き方でプルダウンを記述したほうが良いと思いng-optionsを薦めました。むしろ私には元のページのselectタブ内のoptionsの値がどのようにng-modelのnameにバインドされているかのほうがよく分かりません。
$scope.$apply()はjavascript内で変更された値が見た目上変わらない場合に使います。サードパーティ製プラグイン等(つまりAngularJSのスコープ外)で$scope内のプロパティの値が変更された場合など、Controller側で値が変更されたことが分からず、画面上の値にバインドが行われないために手動でバインドするというのがこのコードの意図です。
実はAngularJS内部では至るところでこの挙動が行われているようです。
今回VBScriptから$scope.$apply()を実行したとのことですが、この場合の$scopeはどこを指しているのでしょうね。意図するような挙動が行われたのかどうかも分かりませんし、元のコードに$scope.$apply()を付与できれば解決するのかどうかも私では判断できません。
お力になれず申し訳ありません。