質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • AngularJS

    587questions

    AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

  • VBScript

    251questions

    VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

VBSでのIE操作(AngularJSのページ)でプルダウン選択が効かない

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 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

+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();を実行してはどうでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 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()を付与できれば解決するのかどうかも私では判断できません。

    お力になれず申し訳ありません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • AngularJS

    587questions

    AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

  • VBScript

    251questions

    VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。