スキップしてメイン コンテンツに移動

ロボット例:ソニー生命個人ページから変額保険の情報を収集する

VBSでIEを操作して仕事をさせるロボット

ソニー生命の個人ページにアクセスして、変額保険の契約者貸付金額と増加保険金額を複数の契約から収集し、その合計額をCSVファイルに出力させるロボット。

人に見せる事を前提に書いてないので美しくない。
当然動作保障なし、サポートもなし。

'***************************************
' IEでソニー生命の変額保険の契約者貸付及び増加保険金合計を取得する。
' 取得した値は"sony.csv"というファイルに日付とともに累積的に出力する。
'***************************************

'***************************************
'グローバル
'***************************************
Const myLogPath = "sony.csv" 'ログ出力ファイル
Const cID = ""     '←アカウント
Const CPW = ""     '←パスワード

Dim ie 'IE
Dim myFSO      ' FileSystemObject
Dim myFile     'ファイル読み込み用
Dim myShell    'シェルオブジェクト

Set myFSO  = WScript.CreateObject("Scripting.FileSystemObject")

Dim myDate '日付
Dim myZoukagaku    '増加保険金額
Dim myKashituke    '貸付金額

myZoukagaku = 0
myKashituke = 0

Main

Private Sub Main()
    Init        '初期処理
    mainProc    '主処理
    EndProc     '終了処理
End Sub

'***************************************
'処理用サブルーチン
'***************************************
Private Sub Init()
'IE 起動
'ログイン画面表示

Const cStartURL  = "https://cs.sonylife.co.jp/lpv/yf1p/sca/PYFW1011.seam?lpk=" 'ソニー生命ログイン画面

    Set ie = CreateObject("InternetExplorer.Application")
    ie.Visible = True
'最大化表示
'    ie.FullScreen = True

    ie.Navigate cStartURL
    Do While ie.Busy = True Or ie.readyState <> 4
    Loop

End Sub

Private Sub EndProc()
'IEの終了
    ie.Quit
    Set ie = Nothing
End Sub

Private Sub mainProc()
    LogIn    'ログイン画面の処理
    TopPage    'トップページの処理
'契約一覧の処理
    listPage    
'契約一覧からトップページへ遷移
    listToTop
    LogOut    ''ログアウトの処理
End Sub

Private Sub listPage()
'契約一覧ページ。
'『変額/外貨詳細情報』が選択可能な契約についてボタンをクリックして紹介画面に遷移する
'選択不可なボタン
'<td class="text6">
'        <div class="textAlign">
'          <img alt="選択する" src="../img/common/dummy_syoukai4.png"></div></td>
'選択可能なボタン
'<td class="text6">
'        <div class="textAlign"><a tabindex="106" href="../../yh2p/scb/PYHW0210.seam?index=2&amp;ETRFLG=1&amp;SDP=1">
'           <img class="rollover" alt="選択する" src="../img/common/dummy_syoukai2.PNG"></a></div></td>

'方針
'Class="test6"の各オブジェクトについて以下を処理する
'<a>タグを持っている→クリック
'<を持っていない>→スルー

    '処理待ち
    Do While ie.Busy = True Or ie.readyState <> 4
    Loop

'18/02/12
'課題
'    一つの契約紹介をして画面を戻し、次のループに入ってくると、
'    "myTag = myTarget.outerHTML" が失敗する。
'    一度別の画面に遷移してしまっているので、
'    "ie.document.getElementsByClassName("text6")"の内容が破棄されている
'    ため、と想像される。
'    別窓もしくは別タブで開こうとすると、『遷移エラー』でサイト側に拒否される。
'    よって
'
'    1.For Each ~ Next でループカウンタを用い、紹介する契約のindexをとる。
'    2.indexを格納した配列について以下処理
'        ・ie.document.getElementsByClassName("text6")を添え字付きでアクセスし、
'          リンク先をクリック。
'        ・待機処理
'        ・shoukai 処理
'
'    ポイントは shoukai 処理でちゃんと契約一覧に戻ってくる事と
'    リンクへアクセスする際、つどオブジェクトに1回ごとに指定しなおす、という所。

dim myTarget
dim myTag
dim myArray()
dim iCnt
    iCnt = 0
    Redim Preserve myArray(iCnt)
    for Each myTarget in ie.document.getElementsByClassName("text6")
        myTag = myTarget.outerHTML        
        Redim Preserve myArray(iCnt)
       If Instr(myTag, "href=") > 0 then
            myArray(iCnt) = True
        Else
            myArray(iCnt) = False
        End If
        iCnt = iCnt + 1
    Next

    For iCnt = 0 To Ubound(myArray)
        If myArray(iCnt) Then
            ie.document.getElementsByClassName("text6")(iCnt).getElementsByTagName("a")(0).click
            Do While ie.Busy = True Or ie.readyState <> 4
            Loop
            shoukai    '契約紹介画面
        End If
    Next

'ログへの出力
    Set myFile = myFSO.OpenTextFile(myLogPath, 8, True)
    myFile.write(myDate & "," & myKashituke & "," & myZoukagaku & VBCRLF)
    myFile.Close
    set myFile = Nothing
'Notepadで開く
    Set myShell = WScript.CreateObject("WScript.Shell") 'シェルオブジェクト定義
'    myShell.Exec("cmd.exe /c Notepad.exe " & myLogPath)
    myShell.Exec("Notepad.exe " & myLogPath)
    Set myShell = Nothing
End Sub

Private Sub shoukai()
'契約の紹介画面
'日付、増加保険金、契約者貸付残高をとる
'リスト画面に戻る

dim tmpM
dim tmpD

'日付
'<div align="right" class="modText02 first-child"><span class="first-child" id="id_inqYy">2018</span>年<span id="id_inqMm">2</span>月<span class="last-child" id="id_inqDd">9</span>日 時点の契約内容
'                  </div>
'月の操作
    If Len(Trim(ie.document.getElementById("id_inqMm").innerText)) < 2 Then
        tmpM = "0" & Trim(ie.document.getElementById("id_inqMm").innerText)
    Else
        tmpM = Trim(ie.document.getElementById("id_inqMm").innerText)
    End If 
'日の操作
    If Len(Trim(ie.document.getElementById("id_inqDd").innerText)) < 2 Then
        tmpD = "0" & Trim(ie.document.getElementById("id_inqDd").innerText)
    Else
        tmpD = Trim(ie.document.getElementById("id_inqDd").innerText)
    End if

    myDate = Trim(ie.document.getElementById("id_inqYy").innerText) & "/" & tmpM & "/" & tmpD

'増加保険金
'<td align="right" class="last-child"><span id="id_vdpAm">-127,906</span>円</td>
    myZoukagaku = myZoukagaku + Clng(Trim(ie.document.getElementById("id_vdpAm").innerText))

'契約者貸付
'<td align="right" class="last-child"><span id="id_ploBl">23,675</span>円</td>
'"-"対策
    If IsNumeric(Trim(ie.document.getElementById("id_ploBl").innerText)) Then
        myKashituke = myKashituke + CLng(Trim(ie.document.getElementById("id_ploBl").innerText))
    End IF
'リスト画面に戻る
'<input tabindex="127" class="modSubmit01" type="submit" value="他の契約を選択する">
Dim myTarget
    For Each myTarget in ie.document.getElementsByTagName("input")
        'myTargetの要素に"他の契約を選択する"を探してクリックする
        If myTarget.value = "他の契約を選択する" Then
            myTarget.Click
            Exit For
        End If
    Next
'処理待ち
    '処理待ち
    Do While ie.Busy = True Or ie.readyState <> 4
    Loop

End Sub

Private Sub listToTop()
'契約一覧からトップページへの遷移
'<input tabindex="113" class="modSubmit01" type="submit" value="トップページに戻る">

Dim myTarget
    For Each myTarget in ie.document.getElementsByTagName("input")
        'myTargetの要素に"トップページに戻る"を探してクリックする
        If myTarget.value = "トップページに戻る" Then
            myTarget.Click
            Exit For
        End If
    Next
'処理待ち
    Do While ie.Busy = True Or ie.readyState <> 4
    Loop
End Sub

Private Sub TopPage()
'トップページで、契約の紹介に遷移する
'オブジェクト:「契約の紹介」ボタン
'<a tabindex="12" href="../../yh1p/scb/PYHW0010.seam?ETRFLG=1"><img width="114" height="47" class="rollover" alt="契約内容の照会" src="../img/common/btn_gn_06.gif"></a>

Const chref = "https://cs.sonylife.co.jp/lpv/yh1p/scb/PYHW0010.seam?ETRFLG=1"

Dim myTarget

    For Each myTarget in ie.document.Links
        If myTarget.href = chref Then
            myTarget.Click
            '処理待ち
            Exit For
        End IF
    Next
    set myTarget = Nothing
'処理待ち
    Do While ie.Busy = True Or ie.readyState <> 4
    Loop
ENd Sub


Private Sub LogOut()
'マイページからログアウトする
'ログアウトボタンのリンク情報
'<a tabindex="5" class="whiteSpace01 first-child" id="logoff_kss_osm_privileged" href="/lpv/yf1p/sca/PYFW1023.seam?lpk=8AU76"><img alt="ログアウト" src="../img/common/btn_logout_ex.png"></a>

Const cID = "logoff_kss_osm_privileged"

Dim myTarget
    
    For Each myTarget In ie.document.Links
        If myTarget.ID = cID Then myTarget.Click 'ログアウト
    Next
    Set myTarget = Nothing
End Sub

Private Sub LogIn()
'***************************************
'ログイン画面処理
'***************************************
'アカウントを入力する
'パスワードを入力する
'「ログイン」をサブミットする

'ログインIDのソース?
'<input id="j_id21:j_id25:acctId" type="text" name="j_id21:j_id25:acctId" class="modInput01 exInput01" style="" tabindex="103" />
'パスワードのソース
'<input id="j_id21:j_id32:pwd1" type="password" name="j_id21:j_id32:pwd1" value="" style="" tabindex="104" class="modInput01 exInput01" />
'ログイン
'<input id="j_id21:logon1_kss_osm_privileged" type="image" src="../img/common/btn_login_01.png?_fp=0Kh99b8Q1W.cvQ1WfzwwCYezo173p7EsKwBI7a.klrZb00AnaCQaJyDEQHaRjg0wVne5DfY_DlVYr.PDFo8BuWnHGCbYfZOANmNFjUNWAJ0WNT.COknYGsUZkOjGye3C2m0yLZQJ2I" name="j_id21:logon1_kss_osm_privileged" alt="&#12525;&#12464;&#12452;&#12531;" tabindex="105" class="rollover" />

'ログインIDを入力する
'表示されているページのインプットボックスの名前を指定して、オブジェクトを取得し、
'そのオブジェクトのVALUE値を入力したい値にする
Const cIDBoxName = "j_id21:j_id25:acctId"    'アカウントインプットボックス
Const cPWBoxName = "j_id21:j_id32:pwd1"      'パスワードインプットボックス
Const cLoginIMGName = "j_id21:logon1_kss_osm_privileged"

Dim strTargetName
Dim myTarget

'ID
    Set myTarget = ie.document.getElementsByName(cIDBoxName)(0)
    myTarget.value = cID

'パスワード
    Set myTarget = ie.document.getElementsByName(cPWBoxName)(0)
    myTarget.value = CPW

'「ログイン」クリック
    Set myTarget = ie.document.getElementsByName(cLoginIMGName)(0)
    myTarget.Click

'処理待ち
    Do While ie.Busy = True Or ie.readyState <> 4
    Loop
End Sub

コメント

このブログの人気の投稿

対処例:Accessフォームでチェックボックスが思うように設定できない

開発プラットフォームとしてAcccessという事は多い。 そして何気に不思議な動作をする事が多いのも事実。 今回であったのは、フォームに置いたチェックボックスが、フォームを開いた際に思ったように振舞ってくれない、というもの。 このチェックボックスは規定値=FALSEで設定してあって、人の操作以外でこのチェックボックスの値は操作していない。 そしてこのチェックボックスを置いたフォームを開くと… 問題のチェックボックス、チェックがついた状態で描画される!!! こまったチャンである。 時折は意図したとおりにOFFの状態で開く場合もあるものの、まれ。 ここはしっかりユーザーの操作(チェックボックスをONにする)に基づき、関連の項目を入力してもらう、という動作をさせたいし、また他へのI/F項目でもあって、しっかりさせたい。ちなみに、TripleState プロパティは Falseに設定してある。 簡単にググッてみたものの、ちょっと同様の事例や対処は見つからず。いくつか試したが、うまく行かない。 で、結論から書くと、こういう対処をした。 Form_OPENイベントの際に、問題のチェックボックスに以下の操作を実行 ・問題のチェックボックスにフォーカス設定 ・問題のチェックボックスに対して、SendKeys でスペース(" ")一文字投げつけ ・問題のチェックボックスの Value 値を確認。True の場合、もう一回SendKey でスペース(" ")一文字投げつけ 発想としては、チェックボックスがカレントな状態のとき、スペースキーで値が操作できる事を思い出し、ぶつけてみた。 でも、実は最初はうまく行かず。 はて? で、 SendKeys のリファレンスを改めて眺めて、 Wait オプションがある事を思い出した。 解説するまでもないが、これが True の場合、そのキーが処理されるまでVBAは次の実行をまつ。デフォルトでは False で実行される。なので、Accessが、なげつけられた?(いや、自分で自分に投げているわけだから…)スペースキーを受け取る前にVBAが進んでるか?と思い、以下に書き換えてやってみた。 SendKeys " ", True ...

VBS で引数を受け取るサンプル

WScript.Arguments に引数要素が配列で格納されているので、これを取り出す。 =========================================== '############################# 'パラメータ=オーダーIDの取り出しとセット '############################# Dim oParam 'パラメータオブジェクト Dim strPrm0  'パラメータ要素格納 Set oParam = WScript.Arguments strPrm0 = oParam(0) Wscript.echo strPrm0 =========================================== これを引数あり、引数なしでそれぞれ実行してみる。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >cscript.exe test.vbs a a >cscript.exe test.vbs test.vbs(9, 1) Microsoft VBScript 実行時エラー: インデックスが有効範囲にありません。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ strPrm0 = oParam(0) の場所で怒られている。 引数なしで起動した場合には相応の対応をしたい。 そこで、上記を書き換える。 WScript.Arguments のCount ポロパティの値をチェックして動作を切り分ける方法。 =========================================== '############################# 'パラメータ=オーダーIDの取り出しとセット '############################# Dim oParam 'パラメータオブジェクト Dim strPrm0  'パラメータ要素格納 Set oParam = WScript.Arguments ...

Accessで環境変数を使う

今回のお題は、ディレクトリの特定の仕方について。 Accessで処理するファイルを、ある場所、具体的にはユーザープロファイルの”ダウンロード”フォルダからアプリのディレクトリに移動したい。 ただ、”ダウンロード”フォルダはログインしているユーザーによって絶対パスが変わってくる。それをどうするか? 今回の場合、ユーザーのリテラシーがそれほど高くなく、ネットからダウンロードされたファイルを、ユーザー自身がファイル選択ダイアログから選んで指示するのは避ける、という判断となった。 一応、ネットからダウンロードされるファイルの保存先はユーザー別の”ダウンロード”フォルダ、という事は保障される前提。 ダウンロードされるファイル名は名前付けルールにそって、識別子のお尻にタイムスタンプが付く。 ただ、Access側での処理のタイミングの問題で、同時に複数のダウンロードファイルを処理するケースも想定された。 個人的には、バッチファイルを同期でアクセスから実行して…、で良いんじゃない?と思った。 それなら環境変数でユーザープロファイルのパスが取れるから。 でも他からの判断でアクセス内で完結させる方法をとる事となった。 で、結局はWSHの ExpandEnvironmentStrings メソッドを使う事にした。 このメソッドは環境変数(%XXXX%)文字列をあたえるとそれの展開結果を返してくれる。 なんで、ExpandEnvironmentStrings("%userprofile%")とすると、ログインユーザーのユーザープロファイルパスが帰ってくる。 なお、これをAccessで使うには参照設定として「Windows Script Host Object Model」 を追加しないといけない。 また、オブジェクトを使うにはアーリーバインディングで書く必要がある事に注意。 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>...