ТЛ; др;
Код ниже работает для данных тестов. С более длинными списками смотрите раздел ToDo
.
API:
Вы хотите заглянуть в API, чтобы предоставить эту информацию, если это возможно. Я считаю, что Alpha Vantage теперь предоставляет информацию, которую использовал Yahoo Finance API *. Здесь есть хорошее руководство по JS . Документация Alpha Vantage здесь . В самом низу этого ответа я кратко рассмотрю функции временных рядов, доступные через API.
Функция веб-сервиса:
С помощью ключа API вы также можете использовать функцию веб-сервиса в Excel для извлечения и анализа данных. Пример здесь . Не тестировалось.
XMLHTTPЗапрос и класс:
Тем не менее, я покажу вам, как использовать класс и цикл по URL. Вы можете улучшить это. Я использую класс «голые кости» под названием clsHTTP
для хранения объекта запроса XMLHTTP. Я даю ему 2 метода. Один, GetHTMLDoc
, для возврата ответа на запрос в HTML-документе, а другой, GetInfo
, для возврата массива интересующих элементов со страницы.
Использование класса таким способом означает, что мы экономим на накладных расходах на многократное создание и уничтожение объекта xmlhttp и предоставляем хороший описательный набор открытых методов для обработки требуемых задач.
Предполагается, что ваши данные такие же, как показано, а строка заголовка - строка 2.
ToDo:
Сразу видно, что IMO - это то, что вы захотите добавить некоторую обработку ошибок. Например, вы можете захотеть разработать класс для обработки ошибок сервера.
VBA:
Итак, в ваш проект вы добавляете модуль класса с именем clsHTTP
и помещаете следующее:
clsHTTP
Option Explicit
Private http As Object
Private Sub Class_Initialize()
Set http = CreateObject("MSXML2.XMLHTTP")
End Sub
Public Function GetHTMLDoc(ByVal URL As String) As HTMLDocument
Dim html As HTMLDocument
Set html = New HTMLDocument
With http
.Open "GET", URL, False
.send
html.body.innerHTML = StrConv(.responseBody, vbUnicode)
Set GetHTMLDoc = html
End With
End Function
Public Function GetInfo(ByVal html As HTMLDocument, ByVal endPoint As Long) As Variant
Dim nodeList As Object, i As Long, result(), counter As Long
Set nodeList = html.querySelectorAll("tbody td")
ReDim result(0 To endPoint - 1)
For i = 1 To 2 * endPoint Step 2
result(counter) = nodeList.item(i).innerText
counter = counter + 1
Next
GetInfo = result
End Function
В стандартном модуле (модуль 1)
Option Explicit
Public Sub GetYahooInfo()
Dim tickers(), ticker As Long, lastRow As Long, headers()
Dim wsSource As Worksheet, http As clsHTTP, html As HTMLDocument
Application.ScreenUpdating = False
Set wsSource = ThisWorkbook.Worksheets("Sheet1") '<== Change as appropriate to sheet containing the tickers
Set http = New clsHTTP
headers = Array("Ticker", "Previous Close", "Open", "Bid", "Ask", "Day's Range", "52 Week Range", "Volume", "Avg. Volume", "Market Cap", "Beta", "PE Ratio (TTM)", "EPS (TTM)", _
"Earnings Date", "Forward Dividend & Yield", "Ex-Dividend Date", "1y Target Est")
With wsSource
lastRow = GetLastRow(wsSource, 1)
Select Case lastRow
Case Is < 3
Exit Sub
Case 3
ReDim tickers(1, 1): tickers(1, 1) = .Range("A3").Value
Case Is > 3
tickers = .Range("A3:A" & lastRow).Value
End Select
ReDim results(0 To UBound(tickers, 1) - 1)
Dim i As Long, endPoint As Long
endPoint = UBound(headers)
For ticker = LBound(tickers, 1) To UBound(tickers, 1)
If Not IsEmpty(tickers(ticker, 1)) Then
Set html = http.GetHTMLDoc("https://finance.yahoo.com/quote/" & tickers(ticker, 1) & "/?p=" & tickers(ticker, 1))
results(ticker - 1) = http.GetInfo(html, endPoint)
Set html = Nothing
Else
results(ticker) = vbNullString
End If
Next
.Cells(2, 1).Resize(1, UBound(headers) + 1) = headers
For i = LBound(results) To UBound(results)
.Cells(3 + i, 2).Resize(1, endPoint-1) = results(i)
Next
End With
Application.ScreenUpdating = True
End Sub
Public Function GetLastRow(ByVal ws As Worksheet, Optional ByVal columnNumber As Long = 1) As Long
With ws
GetLastRow = .Cells(.Rows.Count, columnNumber).End(xlUp).Row
End With
End Function
Результаты:
Примечания к методу GetInfo
и селекторам CSS:
Метод класса GetInfo
извлекает информацию из каждой веб-страницы, используя селектор комбинации css для определения стиля страницы.
Информация, которую мы ищем на каждой странице, размещается в двух смежных таблицах, например:
Вместо того, чтобы возиться с несколькими таблицами, я просто нацеливаюсь на все ячейки таблицы в элементах тела таблицы с помощью комбинации селекторов tbody td
.
Селекторная комбинация CSS применяется с помощью querySelectorAll
метода HTMLDocument
, возвращающего статический nodeList
.
Возвращенные элементы nodeList
имеют заголовки с четными индексами и необходимые данные с нечетными индексами. Мне нужны только первые две таблицы информации, поэтому я прекращаю цикл над возвращенным nodeList
, когда я дал вдвое больше длины интересующих заголовков. Я использую цикл шага 2 из индекса 1 для извлечения только интересующих данных, за исключением заголовков.
Пример того, как выглядит nodeList
:
Ссылки (VBE> Инструменты> Ссылки):
- Библиотека объектов Microsoft HTML
Alpha Vantage API:
Быстрый просмотр вызова time series API
показывает, что можно использовать строку
https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=AA&outputsize=full&apikey=yourAPIKey
Это дает JSON-ответ, что в под-словаре Time Series (Daily)
общего возвращаемого словаря возвращено 199 дат. Каждая дата имеет следующую информацию:
Немного покопавшись в документации, вы узнаете, возможно ли связывание тикеров, я не смог быстро это увидеть и можно ли получить больше ваших начальных предметов, представляющих интерес, через другую строку запроса.
Более подробная информация, например, об использовании функции TIME_SERIES_DAILY_ADJUSTED
в URL-вызове
https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=AA&outputsize=full&apikey=yourAPIkey
Здесь вы получите следующее:
Вы можете проанализировать ответ JSON, используя JSON-анализатор, такой как JSONConverter.bas , а также есть варианты для загрузки в csv.
* Стоит немного изучить, какие API обеспечивают наибольшее покрытие ваших товаров.Похоже, что Alpha Vantage не покрывает столько, сколько извлекает мой код выше.