Как извлечь веб-данные в Visual Basic для приложений, используя XML HTTP-запросы? - PullRequest
2 голосов
/ 09 апреля 2019

Версия: Microsoft Visual Basic для приложений 7.1

Я работаю над небольшим персональным проектом по извлечению и извлечению веб-данных. Мой вопрос касается извлечения данных.

Извлечение данных с веб-страницы с использованием IE работает, но выполняется очень медленно, и по этой причине я склоняюсь к использованию XML-HTTP-запросов. Однако, когда я попробовал это на веб-сайте, над которым я планирую работать, я не мог извлечь данные, которые мне нужны, за исключением некоторого статического содержимого. Изучив текст ответа, я обнаружил, что он не содержит данных, которые мне нужны. Вероятно, это генерируется JavaScript или аналогичными технологиями. Я не уверен, что эти сценарии отображаются в VBA с использованием XML-запросов XML, как в веб-браузерах.

Также интересно отметить, что при просмотре веб-страницы из Developer Tools> Network он предоставляет URL-адрес запроса , в котором ответ содержит большую часть данных, которые мне нужны, но находятся в JSON. формат. Я не знаю, как его проанализировать, но я просто предоставил эту информацию, чтобы вы могли указать мне правильное направление на тот случай, если извлечь данные из динамической веб-страницы с помощью HTTP-запроса XML невозможно.

Я надеюсь, что вы можете потратить пару минут, чтобы увидеть мой код и узнать, где я мог сделать это неправильно.

Спасибо всем большое. Буду очень признателен за вашу помощь.

Вот основная идея того, что я пытаюсь сделать:

С XML (невозможно извлечь необходимые данные):

Option Explicit

Sub dataMinExProject_XML()

    Dim xmlPage As MSXML2.XMLHTTP60
    Dim htmlDoc As MSHTML.HTMLDocument
    Dim coName As MSHTML.IHTMLElement
    Dim secSym As MSHTML.IHTMLElement
    Dim closePrice As MSHTML.IHTMLElement
    Dim URL As String

    URL = "https://www.pse.com.ph/stockMarket/companyInfo.html?id=260&security=468&tab=0"

    Set xmlPage = New MSXML2.XMLHTTP60
    With xmlPage
        .Open "POST", URL, False
        .send
    End With

    Do Until xmlPage.ReadyState = 4
        DoEvents
    Loop

    Set htmlDoc = New MSHTML.HTMLDocument
    htmlDoc.body.innerHTML = xmlPage.responseText

    Set coName = htmlDoc.getElementById("comTopInfoHead").Children(0)
    Set secSym = htmlDoc.getElementById("secSymbol")
    Set closePrice = htmlDoc.getElementById("headerLastTradePrice")

    Debug.Print "Company Name: ", """" & coName.innerText & """"
    Debug.Print "Security Symbol: ", """" & secSym.innerText & """"
    Debug.Print "Closing Price: ", """" & closePrice.innerText & """"

    xmlPage.abort
    Set xmlPage = Nothing
    MsgBox ("alright!")

End Sub

Immediate Window

Company Name:               "BDO Unibank, Inc."
Security Symbol:            ""
Closing Price:              "  "

При рассмотрении Непосредственного окна он показывает, что Security Symbol и Closing Price не были извлечены.

Просто для сравнения и чтобы доказать, что извлекаемые данные существуют, я также предоставил здесь свой код, который использует экземпляр IE.

С IE (данные извлекаются, но работает относительно медленно):

Option Explicit

Sub dataMinExProject_IE()

    Dim ieApp As SHDocVw.InternetExplorer
    Dim htmlDoc As MSHTML.HTMLDocument
    Dim coName As MSHTML.IHTMLElement
    Dim secSym As MSHTML.IHTMLElement
    Dim closePrice As MSHTML.IHTMLElement
    Dim URL As String

    URL = "https://www.pse.com.ph/stockMarket/companyInfo.html?id=260&security=468&tab=0"

    Set ieApp = New SHDocVw.InternetExplorer
    With ieApp
        .Navigate (URL)
        .Visible = vbTrue
    End With

    Do Until ieApp.ReadyState = READYSTATE_COMPLETE
        DoEvents
    Loop

    Set htmlDoc = ieApp.Document

    Set coName = htmlDoc.getElementById("comTopInfoHead").Children(0)
    Set secSym = htmlDoc.getElementById("secSymbol")
    Set closePrice = htmlDoc.getElementById("headerLastTradePrice")

    Do Until secSym.innerText <> vbNullString And closePrice.innerText <> vbNullString
        Loop
    DoEvents

    Debug.Print "Company Name: ", """" & coName.innerText & """"
    Debug.Print "Security Symbol: ", """" & secSym.innerText & """"
    Debug.Print "Closing Price: ", """" & closePrice.innerText & """"

    ieApp.Quit
    Set ieApp = Nothing
    MsgBox ("alright!")

End Sub

Immediate Window

Company Name:               "BDO Unibank, Inc."
Security Symbol:            "BDO"
Closing Price:              "130.50"

Глядя на «Немедленное окно», оно показывает, что оно успешно извлекло данные. Однако, как я уже говорил ранее, его низкая производительность заставила меня взглянуть на другие варианты.

Ссылки:

Веб-очистка маскированного URL с использованием VBA

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Существует набор API .В настоящее время конечная точка Stock API, похоже, не работает.Я поднял вопрос.Если он снова заработает, вы можете использовать следующий синтаксис.Анализатор json: jsonconverter.bas .Вы добавляете .bas к своему проекту и идете VBE> Инструменты> Ссылки> Добавить ссылку на среду выполнения сценариев Microsoft

Option Explicit
Public Sub dataMinExProject_XML()
    Dim xmlPage As MSXML2.XMLHTTP60, aDate As String, symbol As String, json As Object, url As String
    Set xmlPage = New MSXML2.XMLHTTP60
    aDate = Format$(Date - 1, "MM-DD-YYYY")
    symbol = "JFC"
    url = "http://pseapi.com/api/Stock/" & symbol & "/" & aDate

    With xmlPage
        .Open "GET", url, False
        .send
        Set json = JsonConverter.ParseJson(.responseText)
    End With
End Sub

Возвращает объект словаря, который вы можете анализировать информацию по ключу

{
    "symbol":"JFC",
    "date":"15/03/2017",
    "open":197.0000,
    "high":197.4000,
    "low":195.0000,
    "close":196.0000,
    "bid":195.5000,
    "ask":196.0000,
    "volume":141740,
    "value":27747934.0000,
    "netForeign":-6464136.0000
}

Итак, для моего примера:

Dim key As  Variant
For Each key In json.keys
    Debug.Print key, json(key)
Next
0 голосов
/ 09 апреля 2019

Работа с HTTP-запросами - путь. Как вы сказали, IE медленный и неэффективный.

После того, как вы нашли запрос, который возвращает интересующие вас данные в качестве ответа, ваша работа относительно проста и, скорее всего, будет включать одно из следующих действий:

  1. Запрос возвращает HTML-страницу в качестве ответа. В этом случае вы должны использовать Microsoft HTML Object Library, назначить HTML-ответ для HTMLDocument и проанализировать объект, используя существующие методы. Для этого вам понадобится ссылка на Microsoft HTML Object Library.
  2. Запрос возвращает строку JSON. В этом случае вы можете сохранить ответ в строковой переменной и проанализировать его для объекта json, используя VBA JSON . Инструкции и примеры, приведенные в ссылке, очень информативны. Используйте онлайн-просмотрщик JSON, чтобы понять структуру ответа, и вы сможете извлечь любую информацию, какую захотите. Для этого вам понадобится ссылка на Microsoft Scripting Runtime, а также на модуль VBA JSON.
  3. Сочетание двух. Например, некоторые запросы могут возвращать HTML-страницу в качестве ответа, который содержит данные в формате JSON. Другие могут возвращать строку JSON, и одним из элементов, содержащихся в ней, может быть, например, таблица HTML. В этом случае комбинация вышеупомянутых рабочих процессов сделает свое дело.

Что касается самого запроса, убедитесь, что вы используете заголовки, которые необходимы для запроса. Заголовок Content-Type: является одним из них и необходим для POST запроса. Вы можете использовать метод .setRequestHeader. Тело запроса, которое содержит параметры запроса, также имеет важное значение. Я предлагаю вам использовать WinHTTP Services, version 5.1 для ваших запросов.

Как только вы освоите их, вы получите полный контроль над данными, которые хотите получить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...