web-dev-qa-db-ja.com

VBAを使用してWebサイトからデータをスクレイピングする

ウェブサイトからデータをスクレイピングしようとしています: http://uk.investing.com/rates-bonds/financial-futures リアルタイム価格のようにvba経由、つまりドイツ語5 YR US 30Y T-Bond、Bobl、Excel Webクエリを試しましたが、Webサイト全体をスクレイピングするだけですが、レートのみをスクレイピングしたいのですが、これを行う方法はありますか?

13
rockNroll

これを行うにはいくつかの方法があります。これは、「Webサイトからデータをスクレイピングする」というキーワードを参照すると、Internet Explorerの自動化のすべての基本が見つかることを期待して書いた答えですが、自分の研究としては価値がないことを覚えておいてくださいカスタマイズできない事前に作成されたコード)。

これはone wayであり、パフォーマンスの観点からは好みません(ブラウザーの速度に依存するため)が、インターネットオートメーションの背後にある理論的根拠を理解するのに適していることに注意してください。

1)ウェブを閲覧する必要がある場合、ブラウザが必要です!そこで、Internet Explorerブラウザーを作成します。

_Dim appIE As Object
Set appIE = CreateObject("internetexplorer.application")
_

2)ブラウザにターゲットWebページを参照するように依頼します。プロパティ「.Visible」を使用することで、ブラウザがその仕事をしているのを見たいかどうかを決定します。コードをビルドするときは_Visible = True_があればいいのですが、コードがデータをスクレイピングするために動作しているときは毎回表示しないのがいいので_Visible = False_です。

_With appIE
    .Navigate "http://uk.investing.com/rates-bonds/financial-futures"
    .Visible = True
End With
_

3)Webページの読み込みには時間がかかります。それで、私はそれが忙しい間待ちます...

_Do While appIE.Busy
    DoEvents
Loop
_

4)さて、ページがロードされました。 US30Y T-Bondの変更をスクレイプしたいとしましょう。InternetExplorerでF12をクリックしてWebページのコードを表示し、ポインター(赤い丸)を使用して、次の要素をクリックします。どうすれば目的に到達できるかを確認したいと思います。

enter image description here

5)私がすべきことは簡単です。まず、IDプロパティによって、値を含むtr要素を取得します。

_Set allRowOfData = appIE.document.getElementById("pair_8907")
_

ここで、td要素のコレクションを取得します(具体的には、trはデータの行であり、tdはそのセルです。8番目を探しているので、書こう:

_Dim myValue As String: myValue = allRowOfData.Cells(7).innerHTML
_

なぜ8ではなく7と書いたのですか?セルのコレクションは0から始まるため、8番目の要素のインデックスは7(8-1)です。このコード行を簡単に分析します。

  • .Cells()td要素にアクセスさせます。
  • innerHTMLは、検索する値を含むセルのプロパティです。

値がmyValue変数に格納されると、IEブラウザーを閉じ、Nothingに設定してメモリを解放できます。

_appIE.Quit
Set appIE = Nothing
_

さて、これで値が得られ、それを使って何でもできます。セル(Range("A1").Value = myValue)に入れるか、フォームのラベル(_Me.label1.Text = myValue_)に入れます。

これはStackOverflowの仕組みではないことを指摘したいと思います。ここでは、特定のコーディングの問題に関する質問を投稿しますが、最初に独自の検索を行う必要があります。私があまり研究努力を示していない質問に答えている理由は、それが数回尋ねられたのを見ているだけであり、これを行う方法を学んだ時に戻って、私はもっと良いことをしたかったのを覚えている始めるためのサポート。ですから、この答えは、単なる「研究入力」であり、最良/最も完全なソリューションではありませんが、同じ問題を抱えている次のユーザーのサポートになることを願っています。私はこのコミュニティのおかげでプログラミングの方法を学んだので、あなたや他の初心者が私のインプットを使ってプログラミングの美しい世界を発見できると思うのが好きだからです。

あなたの練習をお楽しみください;)

69
Matteo NNZ

他の方法が言及されたので、執筆の時点で、私たちは21世紀にあることを認めてください。 ローカルバスブラウザーを開き、flyXMLHTTP GET リクエスト(XHR GET forショート)。

Wiki moment:

XHRはオブジェクト形式のAPIであり、そのメソッドはWebブラウザーとWebサーバーの間でデータを転送します。オブジェクトはブラウザのJavaScript環境によって提供されます

これは、ブラウザーを開く必要のないデータを取得するための高速な方法です。サーバー応答はHTMLDocumentに読み込まれ、そこからテーブルを取得するプロセスが続行されます。

次のコードでは、テーブルはそのID cr1

table

ヘルパーサブWriteTableでは、列(tdタグ)をループし、次にテーブル行(trタグ)をループし、最後に各テーブル行の長さを走査します。テーブルセルごと。列1と8からのデータのみが必要なので、Select Caseステートメントは、シートに書き込まれる内容を指定するために使用されます。


サンプルWebページビュー:

Sample page view


サンプルコード出力:

Code output


VBA:

Option Explicit
Public Sub GetRates()
    Dim html As HTMLDocument, hTable As HTMLTable '<== Tools > References > Microsoft HTML Object Library

    Set html = New HTMLDocument

    With CreateObject("MSXML2.XMLHTTP")
        .Open "GET", "https://uk.investing.com/rates-bonds/financial-futures", False
        .setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" 'to deal with potential caching
        .send
        html.body.innerHTML = .responseText
    End With

    Application.ScreenUpdating = False

    Set hTable = html.getElementById("cr1")
    WriteTable hTable, 1, ThisWorkbook.Worksheets("Sheet1")

    Application.ScreenUpdating = True
End Sub

Public Sub WriteTable(ByVal hTable As HTMLTable, Optional ByVal startRow As Long = 1, Optional ByVal ws As Worksheet)
    Dim tSection As Object, tRow As Object, tCell As Object, tr As Object, td As Object, r As Long, C As Long, tBody As Object
    r = startRow: If ws Is Nothing Then Set ws = ActiveSheet
    With ws
        Dim headers As Object, header As Object, columnCounter As Long
        Set headers = hTable.getElementsByTagName("th")
        For Each header In headers
            columnCounter = columnCounter + 1
            Select Case columnCounter
            Case 2
                .Cells(startRow, 1) = header.innerText
            Case 8
                .Cells(startRow, 2) = header.innerText
            End Select
        Next header
        startRow = startRow + 1
        Set tBody = hTable.getElementsByTagName("tbody")
        For Each tSection In tBody
            Set tRow = tSection.getElementsByTagName("tr")
            For Each tr In tRow
                r = r + 1
                Set tCell = tr.getElementsByTagName("td")
                C = 1
                For Each td In tCell
                    Select Case C
                    Case 2
                        .Cells(r, 1).Value = td.innerText
                    Case 8
                        .Cells(r, 2).Value = td.innerText
                    End Select
                    C = C + 1
                Next td
            Next tr
        Next tSection
    End With
End Sub
5
QHarr

internet Explorerの代わりにwinhttprequestオブジェクトを使用できます。広告を含む完全なWebページをダウンロードする代わりに写真n広告を除くデータをロードするとよいです。

1
Nitin k tomar

私はポップアップエラーを修正しましたが、最終的には必要に応じてデータを抽出するのにうまく機能しました:

Sub get_data_web()

Dim appIE As Object
Set appIE = CreateObject("internetexplorer.application")

With appIE
    .navigate "https://finance.yahoo.com/quote/NQ%3DF/futures?p=NQ%3DF"
    .Visible = True
End With

Do While appIE.Busy
    DoEvents
Loop

Set allRowofData = appIE.document.getElementsByClassName("Ta(end) BdT Bdc($c-fuji-grey-c) H(36px)")

Dim i As Long
Dim myValue As String

Count = 1

    For Each itm In allRowofData

        For i = 0 To 4

        myValue = itm.Cells(i).innerText
        ActiveSheet.Cells(Count, i + 1).Value = myValue

        Next

        Count = Count + 1

    Next

appIE.Quit
Set appIE = Nothing


End Sub
0
user8608712

この質問はずっと前に尋ねられました。しかし、初心者には次の情報が役立つと思いました。実際、このようなクラス名から値を簡単に取得できます。

Sub ExtractLastValue()

Set objIE = CreateObject("InternetExplorer.Application")

objIE.Top = 0
objIE.Left = 0
objIE.Width = 800
objIE.Height = 600

objIE.Visible = True

objIE.Navigate ("https://uk.investing.com/rates-bonds/financial-futures/")

Do
DoEvents
Loop Until objIE.readystate = 4

MsgBox objIE.document.getElementsByClassName("pid-8907-last")(0).innerText

End Sub

また、Webスクレイピングを初めて使用する場合は、このブログ投稿をご覧ください。

Webスクレイピング-基本

また、Webページからデータを抽出するさまざまな手法があります。この記事では、それらのいくつかについて例を挙げて説明します。

Webスクレイピング-Webページからのデータ収集

0