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

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

新規登録して質問してみよう
ただいま回答率
85.48%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

2回答

8165閲覧

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

GoogleWindows

総合スコア23

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2019/08/02 00:48

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

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

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

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

VBA

1Sub N_YUUBIN() 2 3 Dim objIE As InternetExplorer 4 Dim UserName As String 5 Dim PassWord As String 6 Dim AuthUrl As String 7 Dim objShell As Object 8 Dim objExec As Object 9 Dim ST As Date 10 Dim ret As String 11 Dim ONETIMEPASS As String 12 Dim Pg As String 13 14 UserName = "未開示" 'ユーザー名 15 PassWord = "未開示" 'パスワード 16 AuthUrl = "未開示" '認証ページのURL 17 18 Set objIE = CreateObject("Internetexplorer.Application") 19 20 objIE.Visible = True 21 Call ieView(objIE, AuthUrl) 22 Call Wait(objIE) 23 24 Dim htmlDoc As HTMLDocument 25 Set htmlDoc = objIE.Document 26 27 htmlDoc.getElementsByName("linIds")(0).Value = UserName 28 htmlDoc.getElementsByName("pwdLinIds")(0).Value = PassWord 29 htmlDoc.getElementsByName("EI012")(0).Click 30 31 Call ieCheck(objIE) 32 Call Wait(objIE) 33 34 htmlDoc.getElementById("daiBiki").Click 35 36 Call Wait(objIE) 37 Call ieCheck(objIE) 38 Call Wait(objIE) 39 40 41  '新しいIEウインドウのハンドルが取得できるまで待機(ここからがトークン付与ページ) 42 Dim ie As Long 43 Do 44 DoEvents 45 ie = FindWindow("IEFrame", "メニュー - Internet Explorer") 46 If ie <> 0 Then 47 Exit Do 48 End If 49 Loop 50 51 52 'objectを新しいウインドウで開いたIEに移すため、開いているIE全部のURL(トークン含む)を取得 53 Dim urlIE As String 54 Dim IE1 As InternetExplorer 55 Dim Doc As HTMLDocument 56 Dim sh As Object 57 Dim win As Object 58 59 Set sh = CreateObject("Shell.Application") 60 For Each win In sh.Windows 61 If win.Name = "Internet Explorer" Then 62 Set IE1 = win 63 IE1.Navigate IE1.LocationURL 64 IE1.Visible = True 65 Do While IE1.Busy = True Or IE1.readyState < READYSTATE_COMPLETE 66 DoEvents 67 Loop 68 Set Doc = IE1.Document 69 Debug.Print IE1.LocationURL ', Doc.title 70 '最後に開いたURLが[urlIE]に格納される 71 urlIE = IE1.LocationURL 72 End If 73 Next 74 Set win = Nothing 75 Set sh = Nothing 76 Set Doc = Nothing 77 Set IE1 = Nothing 78 79 Dim objIE2 As InternetExplorer 80 Dim htmlDoc2 As HTMLDocument 81 82 '新しいウインドウで開いたIEをURLから探してobjectに入れる 83 Set objIE2 = ieFind(urlIE) 84 Set htmlDoc2 = objIE2.Document 85 86 Do 87 DoEvents 88 On Error Resume Next 89 ONETIMEPASS = htmlDoc2.getElementsByName("PS_SCREEN_UNIQUE_ID")(0).Value 90 If ONETIMEPASS <> "" Then 91 Exit Do 92 End If 93 Loop 94 95 Pg = "https://未開示PS_SCREEN_UNIQUE_ID=" & ONETIMEPASS 96 97 Call Wait(objIE) 98 Call ieView(objIE, Pg) 99 Call Wait(objIE) 100 101 'ダウンロードリンクボタン 102 htmlDoc.getElementsByName("E325")(0).Click 103 104End Sub 105

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

VBA

1Do 2DoEvents 3On Error Resume Next 4ONETIMEPASS = htmlDoc2.getElementsByName("PS_SCREEN_UNIQUE_ID")(0).Value 5If ONETIMEPASS <> "" Then 6Exit Do 7End If 8Loop

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2019/08/04 03:33

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

回答2

0

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

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

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

投稿2019/08/04 03:45

meg_

総合スコア10579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

GoogleWindows

2019/08/04 09:36

meg様 ご回答ありがとうございます。 objFrameをobjectで宣言して実行したところ、 「オブジェクトは、このプロパティまたはメソッドをサポートしていません」と出ます。 こちらでもframe関連のコードをあれこれ試していたのですが、 該当のframeは見つからないと返ってくるばかりでした。 ちなみにフレームワークはStrutsであることが判明しました。 何かのヒントになれば幸いです。
meg_

2019/08/04 09:51

すみません。getElementsByNameの前にdocument.が抜けていました。 objFrame("mainFrame").document.getElementsByName("PS_SCREEN_UNIQUE_ID")(0).Value
GoogleWindows

2019/08/04 10:04

早速のご返答、感謝いたします。 今度は、 「オブジェクトはこの動作をサポートしていません」と出ました。 ちなみに、 objFrame("mainFrame").objIE.Document.getElementsByName("PS_SCREEN_UNIQUE_ID")(0).Value これでもダメでした。 objFrameの宣言はObjectで合っておりますでしょうか?
meg_

2019/08/04 10:07

objFrameはObject型で良いと思います。 Set objFrame = objIE.document.frames の後で、objFrame  は「Nothing」になっているのでしょうか?(=フレームの取得に失敗)
GoogleWindows

2019/08/04 11:04

度々ありがとうございます。 objFrameにはしっかり入っていますね。 ちなみに"mainFrame"を"frameset"や"frame"にしても 同じエラーになりました。 HTMLソース全取得で表示されるframesetさえ取得できないのですから 難しいのかもしれません。
meg_

2019/08/04 12:05

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

2019/08/04 12:43

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

2019/11/25 08:30

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

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などで数や名前を確認してみては?

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

投稿2019/11/25 20:03

ken3_rougai_pg

総合スコア32

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問