VBAでスクレイピングを実現する方法を教えてください

このQ&Aのポイント
  • Excelマクロを使ってVBAでスクレイピングを行いたいと思っていますが、うまくいきません。
  • 具体的には、クエリを投げて返ってくるページを切り出してセルに格納したいのです。
  • 現在のコードではセルの値に合致するデータだけを取得する方法が見つかっていません。
回答を見る
  • ベストアンサー

VBAでスクレイピング

エクセルマクロを用いてスクレイピングをしようと思っているのですがなかなか思うようにいきません。 やっていることはクエリを投げてかえってくるページを切り出してセルに格納したいというものです。 以下、コードの一部になります。 objX = objIE.Document.getElementById("xx").getElementsByTagName("yy") For n = 0 To objX.Length -1 If InStr(objX(n).OuterHTML, "zz") > 0 Then Cells(1, n+2) = objX(n).InnerText Sleep(1000) End If Next こんな感じです。 やりたいこととしては 1. Cell(1,1)に入ってる数字でクエリ投げる 2.ページを表示 ---ここまではできました--- 3.idだけでは絞れなかったのでTagで絞って連想配列(?)化 4.さらにclass属性=zzのタグだけ抽出 5.それを1行目に要素分だけ列で代入 n+2の部分をどうにかして合致するセルだけ詰めて入力というのはどうやるんでしょうか?今のままではデータはとれますが空欄を処理せねばなりませんで、とても煩わしいです。 Cell(1,2) = objX(n).InnerTextとすると一個目しかとってこれないし… getElementsByClassNameがあれば解決なのでしょうが…IEの挙動が怪しくて使えません。 どうにかなりませんか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

勘違いであれば、ごめんなさい。 以下のようにすればよいと思いますが、そんな単純なことではないのでしょうか。 objX = objIE.Document.getElementById("xx").getElementsByTagName("yy") i=0 For n = 0 To objX.Length -1 If InStr(objX(n).OuterHTML, "zz") > 0 Then Cells(1, i+2) = objX(n).InnerText i = i + 1 Sleep(1000) End If Next それから Sleep(1000) は何のために実行しているのでしょうか。

tomtombouze
質問者

お礼

あ、なるほど…うっかりしておりました、もういっこ変数入れて回せばよいだけですね… Sleepに深い意味はありません、これもループになっていて実際はCell(x, i+2)のような感じで処理するのであまり素早くまわすと捕まるかなと思いまして一応いれていますが、画面表示した段階でのSleepは意味ないかもですね。 ありがとうございました。

関連するQ&A

  • VBA IE操作 スクレイピング

    VBA IE操作について こんばんわ。いつもお世話になっております。 初心者の質問ですが、先生方のご意見ご指導宜しくお願いいたします。 OS : windows7 , EXCEL2007 -------------------------------------------------------------- プロ野球のサイトにアクセスし、(セントラル・リーグ)の球団に在籍する選手 の画像を自動で取得するコードを作りたいと思っています。 (1) 2012年度 選手一覧 → http://bis.npb.or.jp/players/ を開く (2) 球団名のリンクをクリックして球団ページへ移動する (3) 球団ページ内の選手名のリンクをクリックして選手ページへ移動する (4) 選手紹介欄の画像を取得する 上記のような行程なのですが、(2)の球団数も6球団あります。 (4)の選手数にしても何十人もいますので、for ~ next でループさせたいと思っています。 このような場合IEで処理することは可能なのでしょうか? 参考サイトなどから沢山のお知恵をいただき、下記のようなコードを試してみたのですが、 エラーとなり、うまくいきませんでした。 sheet1       A 1 2 3  中日ドラゴンズ 4  東京ヤクルトスワローズ 5  読売ジャイアンツ 6  阪神タイガース 7  広島東洋カープ 8  広島東洋カープ 9  横浜DeNAベイスターズ Sub Test () Sub Graph_Down2() Dim nmbr As Integer nmbr = Range("A3").End(xlDown).Row - 2 Set objIE = CreateObject("InternetExplorer.Application") 'IEを開く objIE.Visible = True objIE.Navigate "http://bis.npb.or.jp/players/" Do While objIE.ReadyState <> 4 'サイトが開くまで待機 Do While objIE.Busy = True Loop Loop For i = 0 To nmbr '表示されているサイトのアンカータグ一つずつを変数objにセット For Each obj In objIE.Document.getElementsByTagName("a") 'Obj.innerTextと全機種名が一致すれば If Trim(Range("A" & i + 3).Value) = Trim(obj.innerText) Then '該当するタグをクリック obj.Click 'ページジャンプ '// '移動したページの画像を取得する処理コードを書く '// objIE.GoBack '前のページへ戻る   '* ここでエラーになります Exit For End If Next Next i ' Set Obj = Nothing ' objIE.Quit ' Set objIE = Nothing End Sub 上記コードですが、 IEで2012年度 選手一覧を開く → A3の球団名と一致したリンクをクリック →  中日ドラゴンズのページに移動 まではできています。 この先の処理についてご指導いただければと思います。 基礎ができていないど素人のため拙い説明ですが、 お分かりの方いましたら是非ご指導願います。 宜しくお願いいたします!

  • VBA、IE操作、初心者になります

    webページの操作についての質問になります。 VBAでやりたいことです。 (1)webページを開き、指定したソースが表示されるまで、画面を更新 (2)ソース表示がされたら、指定したボタンをクリック (3)画面が移行する (4)移行したページの指定したボタンをクリック 不具合 (2)ボタンクリック後、ページは移行するが(4)のボタンが押せません。 しかし(3)のページを直接指定して開いた後に(4)の動作を行うときちんとボタンクリックが出来ます。 順番に(1)→(2)→(3)→(4)と処理を行うと(4)のボタンが押せないという状況です。 こんな感じで作成しました。 Dim objIE As InternetExplorer ' Set objIE = CreateObject("Internetexplorer.Application") objIE.Visible = True Dim strUrl As String strUrl = "●●●●●●?sc_i=shp_pc_top_mdItemRanking_01" objIE.navigate strUrl Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE Loop (1)の処理 Do While (True) If (TypeName(objIE.document.getElementsByClassName("●●●●")(0)) <> "Empty") Then Set tmp = objIE.document.getElementsByClassName("●●●●") flag = False For Each t In tmp If (InStr(t.getAttribute("class"), "●●●●") > 0) Then t.Click flag = True Exit For End If Next End If If (flag = True) Then Exit Do Application.Wait [Now() + "0:00:00.5"] objIE.Refresh Do Loop Until (objIE.Busy = False) And (objIE.readyState = 4) Loop (3)の画面移行 (4)の処理 Set objINPUT = objIE.document.getElementsByTagName("INPUT")  For n = 0 To objINPUT.Length - 1 If InStr(objINPUT(n).Value, "●●●●") > 0 Then objINPUT(n).Click Exit For End If Next Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE Loop Set objINPUT = Nothing 以上になります。 お手数ですが、どなたかご教示をお願いいたします。

  • VBAにて、セルの内容と一致しない場合の処理

    VBAを独学で学んでいる者です。 実力・知識がないながらも検索エンジンなどを頼りに頑張っています。 しかしながらどうしてもわからない事があり、煮詰まってしまいましたので、質問させていただきました。 当方、VBAにてIEを操作し、セルの内容を自動入力していくプログラムを書いています。 以下に記述しているものや、「document.body.innertext」で取得したIEの情報と書き込みたいセルの内容が一致しない場合にエラーメッセージを表示したいのですが、どうもうまくいきません。 If~Thenなどを使うことで条件分岐できるのだとはおもうのですが、当方の記述ですと条件を無視(?)してElseに飛んでしまいます。 当方が記述している内容は以下です。 (Cells(1, 1)には文字列を入力しています。) ~ここから~ 'リンク情報からオブジェクトを探し.Clickする For n = 0 To objIE.document.Links.Length - 1 'リンク数分まわす Debug.Print objIE.document.Links(n).innertext 'デバックで表示する 'リンク先(.text)をチェックする(文字列比較する) If objIE.document.Links(n).innertext = ActiveSheet.Cells(1, 1).Text Then objIE.document.Links(n).Click '.Clickでクリックしてみた Exit For '見つかったので強制的にループを抜ける Else MsgBox "NG!!", vbExclamation Exit Sub End If Next ~ここまで~ Else MsgBox "NG!!", vbExclamation Exit Sub を消すと、「For n = 0 To objIE.document.Links.Length - 1 」がinnertextを取得し、Cells(1, 1)の内容を読み取りクリックを実行してくれるのですが、Elseを入れると、Cells(1, 1)の内容と一致しているにも関わらず、Elseへ移行し、NGのメッセージボックスが出てきます。 記述が間違っているのでしょうか? 何か他の記述がございますようでしたらご教授願えますでしょうか? 宜しくお願い致します。

  • VBAでIEのページを(メニュー選択)進める

    エクセルのVBAでIEのページを(メニュー選択)進める件ですが Dim tag As String Dim objtag As Object in_str = "新しく記事を書く" tag = "li" Set objtag = doc.getElementsByName(tag)(0) For Each objtag In IE.document.getElementsByTagName(tag)   If InStr(objtag.outerHTML, in_str) > 0 Then    Exit For   End If Next Debug.Print objtag.outerHTML objtag.Click For は 機能していて、Debug は <LI><A href="?mode=editor&amp;process=new">新しく記事を書く</A> で 止まっています。 で、叩く方法は?? Click が機能しないのですが objtag. の 後に お助け文字が全く出ませんので、行き詰りました。

  • 【VBA】IEのリンクを新しいタブで開く

    VBAでIEを制御しリンク(アンカー)<a href="***">を新しいタブで開くようにしたいのですが可能でしょうか? 仮にグーグルのトップページ(http://www.google.co.jp/)の『検索オプション』(http://www.google.co.jp/advanced_search?hl=ja)を新しいタブで開くとします 実際に開きたいリンクのURLは固定ではないためURLの指定では開けませんが、飛びたいリンクの文言(『検索オプション』)は固定です リンクに飛ぶ前に飛ぶ先のURLを取得する仕方か、Shift+Ctrl+クリックのようにリンクを新しいタブで開く方法を教えてください 一度普通にリンクに飛んでからURLを取得し、戻ってから新しいタブで開くぐらいしかできないのでしょうか? Sub 新しいタブで開く() Dim objIE As Object Dim objShell Dim URL As String Set objShell = CreateObject("Shell.Application") For n = objShell.Windows.Count To 1 Step -1 Set objIE = objShell.Windows(n - 1) If Right(UCase(objIE.FullName), 12) = "IEXPLORE.EXE" Then objIE.Navigate "http://www.google.co.jp/" Exit For End If Next Set objShell = Nothing objIE.Visible = True Do While objIE.Busy = True Or objIE.ReadyState <> 4 DoEvents Loop For Each Obj In objIE.Document.getElementsByTagName("a") If Obj.innerText = "検索オプション" Then Obj.Click Do While objIE.Busy = True Or objIE.ReadyState <> 4 DoEvents Loop URL = objIE.Document.URL objIE.GoBack Do While objIE.Busy = True Or objIE.ReadyState <> 4 DoEvents Loop objIE.Navigate URL, CLng(&H800) Exit For End If Next End Sub よろしくお願いいたします

  • VBSでIEのログイン画面でのアカウントの自動設定について

    VBSで自動で起動したIEのログイン画面にアカウントを設定するやり方について 書籍にログインページであるという認識が Set objIE = Createobject("InternetExplorer.Application") If InStr(1, objIE.Document.Body.InnerText, "ログイン") > 0とありますが これはログインページをHTML形式で見た時にBodyタグの中に 「ログイン」があればログインページと認識できるということなのでしょうか? よくわからないのでよろしくお願いします。

  • 【Excel VBA】ウェブサイトの自動ログイン

    VBAでRedHatのホームページに自動ログインするプログラムを作成しています。 <コード> Sub RedHat() Dim objIE As InternetExplorer Dim urlName As String Set objIE = CreateObject("InternetExplorer.Application") objIE.Visible = True Call ieView(objIE, "https://idp.redhat.com/idp") If objIE.LocationURL <> "https://idp.redhat.com/idp" Then Call ieNavi(objIE, "https://www.redhat.com/wapps/ugc/protected/account.html") Call tagClick(objIE, "li", "utility-account") Call tagClick(objIE, "p", "ログアウト") Call ieNavi(objIE, "https://idp.redhat.com/idp") End If Call formText(objIE, "username", "丸秘") Call formText(objIE, "password", "丸秘") Call tagClick(objIE, "button", "ログイン") Set objIE = Nothing End Sub Function ieView(objIE As InternetExplorer, _ urlName As String) objIE.navigate urlName Call ieCheck(objIE) End Function Function ieCheck(objIE As InternetExplorer) As String Do While objIE.Busy Or objIE.readyState < 4 DoEvents Loop End Function Function tagClick(objIE As InternetExplorer, _ tagName As String, _ tagStr As String) For Each objTag In objIE.document.getElementsByTagName(tagName) If InStr(objTag.outerHTML, tagStr) > 0 Then objTag.Click Call ieCheck(objIE) Exit For End If Next End Function Function ieNavi(objIE As InternetExplorer, _ urlName As String) objIE.navigate urlName Call ieCheck(objIE) End Function Function formText(objIE As InternetExplorer, _ nameValue As String, _ tagValue As String) For Each objTag In objIE.document.getElementsByTagName("input") If objTag.Name = nameValue Then objTag.Value = tagValue Exit For End If Next For Each objTag In objIE.document.getElementsByTagName("textarea") If objTag.Name = nameValue Then objTag.Value = tagValue Exit For End If Next End Function "丸秘"をユーザとパスワードに修正し、 実行しました。 実行後、IE画面で以下のメッセージが表示されます。 「RedHatのログイン画面でユーザ名またはパスワードが無効です」 ユーザ欄がクリックされている状態になります。 すみません。どの行を何に修正すれば、正常に動作しますでしょうか? 教えていただけますと幸いです。 引用元:http://www.vba-ie.net/application/twitter-login.html

  • VBAでIEの操作→サブウインドウを操作するには

    以下の「oya.html」「ko.html」があります。 それを、VBAで「oya.html」を開き、「子ウインドウを開く」リンクをクリックさせて、開いた「ko.html」の「子ウィンドウを閉じる」リンクをクリックさせたいのだがどうすればよろしいでしょうか? ---------VBA ↓--------------------------------------------- Private Sub CommandButton1_Click() Dim objIE As Object 'Object型 'IEのオブジェクトを作る Set objIE = CreateObject("InternetExplorer.application") objIE.Visible = True objIE.Navigate "file:///C:/oya.html"'「oya.html」を開く '----表示待ち↓-------- Do While objIE.Busy  DoEvents Loop Do While objIE.document.ReadyState <> "complete" DoEvents Loop '----表示待ち↑---------- For Each linkitem In objIE.document.all.tags("A") 'Aタグ If linkitem.innerText = "子ウインドウを開く" Then linkitem.Click End If Next '----表示待ち↓-------- Do While objIE.Busy DoEvents Loop Do While objIE.document.ReadyState <> "complete" DoEvents Loop '----表示待ち↑----------   For Each linkitem In objIE.document.all.tags("A") 'Aタグ If linkitem.innerText = "子ウィンドウを閉じる" Then linkitem.Click End If Next End Sub ---------------↑------------------------------------------- --------oya.html ↓----------------------------------------- <html> <head><script> function showModal(){ var value = showModalDialog('ko.html'); } </script></head> <TITLE>親ウィンドウ</TITLE> <body> <a href="javascript://" onclick="showModal()">子ウインドウを開く</a><br> </body> </html> -----------------↑----------------------------------------- --------ko.html ↓-------------------------------------------- <html> <TITLE>子ウィンドウ</TITLE> <body> <a href="#" onClick="window.close(); return false;">子ウィンドウを閉じる</a><br> </body> </html> ------------------↑-----------------------------------------

  • VBAでJAVAをコントロール

    javascriptのリンクが、<a href="javascript:void(0);">なんたらかんたら</a> であれば記載のソースが通じるのですが、 【今回の問題】 【html部分】 onclick="javascript:updateDisp();return false;" alt="なんたらかんたら"><input type="hidden" name="allupdate" value="なんたらかんたら"> 【javascriptの部分】 function updateDisp(){ update_flg = window.confirm("なんたらかんたら"); if(update_flg == true){ document.updateForm.submit(); } else{ alert("キャンセルしました。"); } とやられた途端に全く通じなくなりました。 どのように回避したらよいでしょうか。 【今回のではなく前回の(javascript:void(0);)成功分】 Private Sub CommandButton99_Click() Set objIE = CreateObject("InternetExplorer.application") objIE.Visible = True objIE.Navigate "http://xxxx/entry" Do While objIE.Busy = True DoEvents Loop Application.Wait (Now + TimeValue("00:00:03")) objIE.Document.all("ShopShopId").Value = Range("C8") objIE.Document.all("ShopPassword").Value = Range("C9") objIE.Document.forms(0).submit Application.Wait (Now + TimeValue("00:00:05")) For Each Obj In objIE.Document.getElementsByTagName("a") If Obj.innerText = "なんたらかんたら" Then Obj.Click Exit For End If Debug.Print objIE.LocationURL objIE.Navigate "xxxx/entry/entry_tops/all_update?prm=xxxxxxxxxxxxxxxxxxxxxxx" For i = 0 To objIE.Document.Links.Length - 1 If objIE.Document.Links(i).href = "javascript:void(0);" Then Application.Wait (Now + TimeValue("00:00:05")) objIE.Document.Links(i).Click Application.Wait (Now + TimeValue("00:00:05")) Exit For MsgBox "ループ抜け" End If Exit Sub Next Next objIE.Quit End Sub 上記は【今回の問題】に通じません。 'objIE.Navigate.Document.updateForm.fireEvent ("なんたらかんたら") 'objIE.Document.Script.updateDisp "javascript:document.updateForm.submit(true);" など試行錯誤しておりますが、javascriptのポップアップが回避できません。 どなたか何とかご教授お願いいたします。

  • VBA IE制御 テーブルコピー

    下記コードは、http://www.ken3.org/vba/backno/vba177.htmlからお借りしているものです。 (一部ヤフーのデザインに変更があったため、変更しています。) 実行してみると、本来7行4列である表が、1行目にすべて入り込んでしまいます。 見直してみても、間違ってはいないように見えるのですが、原因はどこかわかりますでしょうか? よろしくお願いいたします。 Sub ie_make_table_test() Dim objIE As Object 'IEオブジェクト参照用 Dim objTAG As Object 'TAGのオブジェクトを代入 Dim strURL As String 'URLの文字列 Dim strTAGNAME As String 'タグの名前保存用 Dim y As Integer Dim x As Integer Dim objTableItem As Object 'TABLE内のITEM検索用 Set objIE = CreateObject("InternetExplorer.application") objIE.Visible = True '文字列で指定したURLに飛ぶ strURL = "http://table.yahoo.co.jp/" 'ベースURL strURL = strURL & "t?c=2004&a=10&b=4&f=2005&d=10" '期間 strURL = strURL & "&e=14&g=d&s=4753.t&y=0&z=4753.t" '銘柄コードなど??? objIE.Navigate strURL 'URLへ '表示終了まで待つ Do While objIE.Busy = True DoEvents Loop '新規ブックを追加する Workbooks.Add 'No.177で修正ブックを新規に1つ作る '.document から.getElementsByTagName("TABLE")でオブジェクトを取り出す For Each objTAG In objIE.document.getElementsByTagName("TABLE") 'TABLEの中、テキスト文字で[値上がり率]があるか、子TABLEは無しかチェック If InStr(objTAG.InnerText, "値上がり率") > 0 _ And InStr(objTAG.InnerHTML, "TABLE") = 0 Then '値上がり率在り、TABLE無しか '新規シートを追加する Sheets.Add 'No.177で修正、新規シートを作成する 'カウンタの初期化 y = 0 '行カウンタ 'テーブル内のITEMでループする For Each objTableItem In objTAG.all strTAGNAME = objTableItem.tagName 'テーブル、タグ名 If strTAGNAME = "TR" Then y = y + 1 '行カウンタを+1 x = 1 '列カウンタを1(左端にする) End If '↓No.177でTHもセットするように変更 TD or THの時 If strTAGNAME = "TD" Or strTAGNAME = "TH" Then 'テキストデータをセットする Cells(y, x) = objTableItem.InnerText x = x + 1 '列カウンタを+1(次にする) End If Next End If Next End Sub