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

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

ただいまの
回答率

89.10%

VBAにおけるWebスクレイピングで、Frameset以下の要素が取得できない

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,031

GoogleWindows

score 11

目的は、日本郵便の法人向けページからPDFをダウンロードすることなのですが、
JavaScriptで右クリックができなくなっていたり、
新しいIEウィンドウで開くため、そちらへObjectを移してあげなければならなかったり、
ダウンロードページに行くまでの全URLにトークンが付与されていたり、
ダウンロードファイルのpath自体にも
トークンとは別のワンタイムパスワードが設定されていて、かなり難儀しております。

新しいIEウインドウの特定と、URLトークンはなんとか取得できたため問題ないのですが、
トークンとは別のワンタイムパスワードがどうしても取得できません。

と言いますのも、そのワンタイムパスワードは、
Framesetの以下要素として存在しており、
ページ内の全htmlソース取得コードを走らせてもその中身が取れません。

まずは、以下が実行コードとなります。
(※未開示箇所が多くて申し訳ございません)

Sub N_YUUBIN()

    Dim objIE As InternetExplorer
    Dim UserName As String
    Dim PassWord As String
    Dim AuthUrl As String
    Dim objShell As Object
    Dim objExec As Object
    Dim ST As Date
    Dim ret As String
    Dim ONETIMEPASS As String
    Dim Pg As String

    UserName = "未開示" 'ユーザー名
    PassWord = "未開示" 'パスワード
    AuthUrl = "未開示" '認証ページのURL

    Set objIE = CreateObject("Internetexplorer.Application")

    objIE.Visible = True
    Call ieView(objIE, AuthUrl)
    Call Wait(objIE)

    Dim htmlDoc As HTMLDocument
    Set htmlDoc = objIE.Document

    htmlDoc.getElementsByName("linIds")(0).Value = UserName
    htmlDoc.getElementsByName("pwdLinIds")(0).Value = PassWord
    htmlDoc.getElementsByName("EI012")(0).Click

    Call ieCheck(objIE)
    Call Wait(objIE)

    htmlDoc.getElementById("daiBiki").Click

    Call Wait(objIE)
    Call ieCheck(objIE)
    Call Wait(objIE)


  '新しいIEウインドウのハンドルが取得できるまで待機(ここからがトークン付与ページ)
    Dim ie As Long
    Do
    DoEvents
        ie = FindWindow("IEFrame", "メニュー - Internet Explorer")
        If ie <> 0 Then
            Exit Do
        End If
    Loop


    'objectを新しいウインドウで開いたIEに移すため、開いているIE全部のURL(トークン含む)を取得
    Dim urlIE As String
    Dim IE1 As InternetExplorer
    Dim Doc As HTMLDocument
    Dim sh As Object
    Dim win As Object

    Set sh = CreateObject("Shell.Application")
    For Each win In sh.Windows
        If win.Name = "Internet Explorer" Then
            Set IE1 = win
            IE1.Navigate IE1.LocationURL
            IE1.Visible = True
            Do While IE1.Busy = True Or IE1.readyState < READYSTATE_COMPLETE
                DoEvents
            Loop
            Set Doc = IE1.Document
            Debug.Print IE1.LocationURL ', Doc.title
        '最後に開いたURLが[urlIE]に格納される
            urlIE = IE1.LocationURL
        End If
    Next
    Set win = Nothing
    Set sh = Nothing
    Set Doc = Nothing
    Set IE1 = Nothing

    Dim objIE2 As InternetExplorer
    Dim htmlDoc2 As HTMLDocument

   '新しいウインドウで開いたIEをURLから探してobjectに入れる
    Set objIE2 = ieFind(urlIE)
    Set htmlDoc2 = objIE2.Document

    Do
    DoEvents
    On Error Resume Next
    ONETIMEPASS = htmlDoc2.getElementsByName("PS_SCREEN_UNIQUE_ID")(0).Value
        If ONETIMEPASS <> "" Then
            Exit Do
        End If
    Loop

    Pg = "https://未開示PS_SCREEN_UNIQUE_ID=" & ONETIMEPASS

    Call Wait(objIE)
    Call ieView(objIE, Pg)
    Call Wait(objIE)

    'ダウンロードリンクボタン
    htmlDoc.getElementsByName("E325")(0).Click

End Sub

試したこと

JavaScriptで動的に展開しなければならない階層にあるのか分かりませんが、
ピンポイントに値を取りに行こうとしても、
ページは完全に開いているのに以下のLoopから抜けてくれません。

Do
DoEvents
On Error Resume Next
ONETIMEPASS = htmlDoc2.getElementsByName("PS_SCREEN_UNIQUE_ID")(0).Value
If ONETIMEPASS <> "" Then
Exit Do
End If
Loop

Typeがhiddenのため取得できないのかと思いきや、
Fremeset⇒Frame以下の値がすべて取得できないようでした。

問題のページのHTMLソースは以下になります。
(※全要素取得コードで得たHTMLソースでは階層状態が分からないため画像にて掲載)

イメージ説明

実現したいこと

画像のコメントにもある通り、
<html lang="ja"><head>以下の子要素が取得できれば、
今回の目的となる

<input type="hidden" name="PS_SCREEN_UNIQUE_ID" value="123456789123456789">

や、

<a href="/JP_未開示PS_SCREEN_UNIQUE_ID=123456789123456789" onclick="return checkSend();">PDFダウンロード</a>

に記載されているワンタイムパスワードが取得できるため、
本当の意味での全要素を取得する方法を、
ヒントや参考ページだけでも何とかお知恵を拝借できませんでしょうか。

何とぞよろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

Win10 x64 
Office2016 x32

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • meg_

    2019/08/04 12:33

    htmlDoc2の中に"PS_SCREEN_UNIQUE_ID"は含まれていますか? デバッグしてみてください。

    キャンセル

回答 2

+1

静的に取得できると仮定すると、
目的のページはフレーム構造になっていますので

1.Set objFrame = objIE.document.frames 'フレーム取得
2.objFrame("mainFrame").getElementsByName("PS_SCREEN_UNIQUE_ID")(0).Value

このようなコードで取得できそうです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/08/04 21:05

    objFrameが取得できているのであれば、
     objFrame("mainFrame")でフレームが取得できているか?
     objFrame("mainFrame").documentは取得出来ているか? 出来ている場合、目的の要素「PS_SCREEN_UNIQUE_ID」はdocumentに含まれているか?
       を1つずつ確認しましょう。

    キャンセル

  • 2019/08/04 21:43

    objFrame("mainFrame")自体が取得できていないようでした。
    どのframeも取得できないのですからもうお手上げですね。
    Strutsの構造的にframe以下はJSで制御しなければならないようなので、
    難しいかもしれません。

    キャンセル

  • 2019/11/25 17:30

    外していたらすいません。
    ObjFrameがとれているなら、name指定ではなくて要素をindexで指定して
    各々の要素の名前を確認してみては?
    名前を見ればどこを見ているか推測できそうな気がします
    あるいはindexの指定すらできないということでしょうか?

    キャンセル

0

もしかして、フレームが三分割されていませんか?

html フレーム 三分割
で検索すると
https://www.tagindex.com/html_tag/frame/frame_examples.html
などがみつかり、ソースの例が出ているのですが

<frameset rows="100,*">

<frame src="example_a.html" name="frame1" title="上フレーム">

<frameset cols="200,*">
    <frame src="example_c.html" name="frame2" title="左フレーム">
    <frame src="example_b.html" name="frame3" title="右フレーム">
</frameset>

</frameset>


↑はじめに、上下に二分割してから、
次に、左右に二分割
これで、三分割のフレームを作成しているページだと、

そのまま、ドキュメントの下のフレームを探るだけだと、
はじめの、上下二つしか見れなくて、
やりたいことは(見たいデータが)
下のフレームが分割された左?や右などにあると、
フレーム多重になているとやっかいかも。

VBA IE フレーム 三分割で検索すると
http://tandyco.cocolog-nifty.com/blog/2008/05/excel_vbaframe_8cda.html

↑孫フレームまでチェックする参考となれば。

他の回答に出ているように、.Nameや.Lengthなどで数や名前を確認してみては?

以上、フレームの三分割を疑ってみました。
※外していたらスミマセン、解決の糸口となれば幸いです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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