Парсинг данных из интернета обычно ассоциируется с Python или специализированными сервисами. Но если данные нужно сразу положить в таблицу, посчитать формулами и показать коллегам — Excel вместе с VBA остаётся одним из самых быстрых способов получить результат. Не нужно ставить интерпретатор, настраивать окружение и объяснять бухгалтеру, что такое pip install. Открыл книгу, нажал кнопку — данные на листе.
В этой статье разберём, как устроен парсинг средствами VBA: какие объекты использовать для HTTP-запросов, как разбирать HTML и JSON, как складывать результат в ячейки и не нарваться на блокировку. Примеры — рабочие, их можно скопировать в редактор VBA и запустить.
Когда Excel / VBA — хороший выбор
VBA имеет смысл брать, когда:
- результат всё равно живёт в Excel (отчёт, дашборд, журнал котировок);
- объём данных небольшой или средний — десятки–тысячи строк, а не миллионы;
- нужна автоматизация «по кнопке» для людей без навыков программирования;
- источник отдаёт данные через простой HTTP-запрос или открытый API.
Если же нужен серьёзный масштаб, обход сложной JavaScript-защиты или параллельные запросы — лучше посмотреть в сторону Python (requests, BeautifulSoup, Playwright). VBA в таких задачах быстро упирается в потолок.
Инструменты внутри VBA
Для парсинга в VBA есть несколько основных «движков»:
| Объект | Назначение | Когда применять |
|---|---|---|
MSXML2.XMLHTTP / ServerXMLHTTP |
HTTP-запросы | Основной способ получить ответ сервера |
WinHttp.WinHttpRequest.5.1 |
HTTP-запросы | Альтернатива с гибкими таймаутами |
HTMLDocument (MSHTML) |
Разбор HTML | Когда нужно вытащить элементы по тегам/классам |
RegExp (VBScript) |
Регулярные выражения | Точечное извлечение из текста |
Split / InStr / Mid |
Строковые функции | Простой разбор JSON и текста без библиотек |
QueryTables / Power Query |
Готовые таблицы | Когда страница отдаёт чистую HTML-таблицу |
Большинство этих объектов подключаются «на лету» через CreateObject, то есть не требуют ручного добавления ссылок в проект. Это удобно: книга работает на любой машине с Excel.
Базовый HTTP-запрос
Самый простой парсер — это получить текст страницы. Вот функция, которая делает GET-запрос и возвращает HTML или JSON как строку:
Function GetResponse(ByVal url As String) As String
Dim http As Object
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", url, False
' Притворяемся обычным браузером — многие сайты режут запросы без User-Agent
http.setRequestHeader "User-Agent", _
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
http.send
If http.Status = 200 Then
GetResponse = http.responseText
Else
GetResponse = "ERROR: " & http.Status & " " & http.statusText
End If
Set http = Nothing
End Function
Третий аргумент Open — False означает синхронный запрос: код ждёт ответа. Для большинства задач этого достаточно. Заголовок User-Agent критичен: без него часть серверов возвращает 403 или капчу.
Разбор JSON без библиотек
VBA не умеет парсить JSON «из коробки», но для простых ответов хватает строковых функций. Допустим, API вернул:
{"price": 152.34, "currency": "USD", "symbol": "AAPL"}
Извлечь значение поля можно небольшой функцией:
Function ExtractJsonValue(ByVal json As String, ByVal key As String) As String
Dim pattern As String
Dim startPos As Long, endPos As Long
pattern = """" & key & """:"
startPos = InStr(json, pattern)
If startPos = 0 Then Exit Function
startPos = startPos + Len(pattern)
' Пропускаем кавычку, если значение строковое
If Mid(json, startPos, 1) = """" Then startPos = startPos + 1
' Конец значения — запятая, закрывающая скобка или кавычка
endPos = startPos
Do While endPos <= Len(json)
Dim ch As String
ch = Mid(json, endPos, 1)
If ch = "," Or ch = "}" Or ch = """" Then Exit Do
endPos = endPos + 1
Loop
ExtractJsonValue = Trim(Mid(json, startPos, endPos - startPos))
End Function
Этот подход работает для плоских объектов. Если структура вложенная и сложная, лучше подключить готовый JSON-парсер для VBA (например, открытый модуль VBA-JSON от Tim Hall) — он превращает ответ в Dictionary и Collection, с которыми удобно работать.
Связка «HTTP-запрос → разбор JSON → запись в ячейку» — это основной шаблон, по которому строится парсинг курсов валют. Большинство сервисов ЦБ и валютных API отдают именно JSON или XML, и описанная выше функция извлечения значений покрывает 80% случаев. Подробный разбор готового решения с автообновлением по таймеру — в материале «Парсинг курсов валют».
Разбор HTML через MSHTML
Когда данные лежат не в API, а прямо в разметке страницы, удобно использовать объект HTMLDocument. Он позволяет искать элементы так же, как в браузере — по id, тегам и классам.
Function ParseHtmlElement(ByVal url As String, ByVal elementId As String) As String
Dim http As Object, htmlDoc As Object
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", url, False
http.setRequestHeader "User-Agent", "Mozilla/5.0"
http.send
Set htmlDoc = CreateObject("htmlfile")
htmlDoc.body.innerHTML = http.responseText
Dim el As Object
Set el = htmlDoc.getElementById(elementId)
If Not el Is Nothing Then
ParseHtmlElement = Trim(el.innerText)
End If
Set http = Nothing
Set htmlDoc = Nothing
End Function
Если нужно вытащить несколько элементов по классу или тегу, пригодится перебор коллекции:
Sub ParseAllRows(ByVal url As String)
Dim http As Object, htmlDoc As Object
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", url, False
http.setRequestHeader "User-Agent", "Mozilla/5.0"
http.send
Set htmlDoc = CreateObject("htmlfile")
htmlDoc.body.innerHTML = http.responseText
Dim rows As Object, i As Long
Set rows = htmlDoc.getElementsByTagName("tr")
For i = 0 To rows.Length - 1
' Пишем текст каждой строки таблицы на лист, начиная со 2-й строки
Cells(i + 2, 1).Value = Trim(rows.Item(i).innerText)
Next i
Set http = Nothing
Set htmlDoc = Nothing
End Sub
Регулярные выражения
Иногда нужное значение спрятано в тексте без удобной обёртки. Тогда выручает RegExp:
Function ExtractByRegex(ByVal text As String, ByVal pattern As String) As String
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Global = False
re.IgnoreCase = True
re.pattern = pattern
Dim matches As Object
Set matches = re.Execute(text)
If matches.Count > 0 Then
' Возвращаем первую группу захвата
ExtractByRegex = matches(0).SubMatches(0)
End If
Set re = Nothing
End Function
' Пример: достать число из строки вида "Цена: 152.34 руб"
' value = ExtractByRegex(s, "Цена:\s*([\d\.]+)")
Запись результата на лист
Записывать данные в ячейки по одной — медленно. Если строк много, собирайте их в массив и выгружайте одним присваиванием:
Sub WriteArrayFast(data() As Variant)
Dim n As Long
n = UBound(data) - LBound(data) + 1
' Выгружаем весь столбец за одну операцию
Range("A1").Resize(n, 1).Value = Application.Transpose(data)
End Sub
Такая выгрузка в десятки раз быстрее, чем цикл с записью в каждую ячейку, особенно при отключённом обновлении экрана:
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' ... парсинг и запись ...
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Практический пример: парсинг таблицы котировок
Соберём небольшой парсер, который проходит по списку тикеров, запрашивает цену через условный API и складывает результат на лист.
Sub ParseQuotes()
Dim tickers As Variant
tickers = Array("AAPL", "MSFT", "GOOGL", "TSLA")
Dim i As Long, url As String, response As String, price As String
' Заголовки таблицы
Cells(1, 1).Value = "Тикер"
Cells(1, 2).Value = "Цена"
Cells(1, 3).Value = "Время"
Application.ScreenUpdating = False
For i = LBound(tickers) To UBound(tickers)
url = "https://example-api.com/quote?symbol=" & tickers(i)
response = GetResponse(url) ' функция из раздела выше
price = ExtractJsonValue(response, "price")
Cells(i + 2, 1).Value = tickers(i)
Cells(i + 2, 2).Value = Val(price)
Cells(i + 2, 3).Value = Now
' Пауза между запросами, чтобы не нагружать сервер и не словить блок
Application.Wait Now + TimeValue("0:00:01")
Next i
Application.ScreenUpdating = True
MsgBox "Готово: загружено " & (UBound(tickers) + 1) & " котировок", vbInformation
End Sub
Это упрощённый каркас. На практике для парсинга котировок акций добавляют разбор объёма торгов, изменения в процентах, исторических данных, а также обработку выходных дней и нерабочих часов биржи. Полную реализацию с автообновлением и условным форматированием смотрите в материале «Парсинг котировок акций».
Обработка ошибок и устойчивость
Сетевые запросы падают: сервер не ответил, таймаут, неверный формат. Парсер должен это переживать, а не вылетать на первой же ошибке.
Function SafeGet(ByVal url As String, Optional retries As Long = 3) As String
Dim attempt As Long
For attempt = 1 To retries
On Error Resume Next
Dim http As Object
Set http = CreateObject("WinHttp.WinHttpRequest.5.1")
http.SetTimeouts 5000, 5000, 10000, 10000 ' resolve, connect, send, receive
http.Open "GET", url, False
http.setRequestHeader "User-Agent", "Mozilla/5.0"
http.send
If Err.Number = 0 And http.Status = 200 Then
SafeGet = http.responseText
On Error GoTo 0
Exit Function
End If
On Error GoTo 0
' Пауза перед повторной попыткой растёт с каждым разом
Application.Wait Now + TimeValue("0:00:0" & attempt)
Next attempt
SafeGet = "" ' все попытки исчерпаны
End Function
Объект WinHttpRequest здесь удобнее XMLHTTP именно из-за метода SetTimeouts — можно явно задать пределы ожидания и не зависнуть навсегда.
Этика и ограничения
Несколько правил, которые экономят нервы и репутацию:
- Читайте
robots.txtи условия использования. Не все сайты разрешают автоматический сбор данных. - Делайте паузы между запросами. Десятки запросов в секунду выглядят как атака и приводят к бану IP.
- Предпочитайте официальные API. Если у источника есть API — используйте его: это стабильнее и легально.
- Не парсите персональные данные без оснований и согласия.
- Кэшируйте результат. Если курс валюты обновляется раз в день, не надо дёргать сервер каждую минуту.
Альтернатива без кода: Power Query
Стоит упомянуть, что для многих задач VBA вообще не нужен. Встроенный в Excel Power Query (Данные → Получить данные → Из интернета) умеет загружать HTML-таблицы и JSON-ответы через интерфейс, с автообновлением по расписанию. Если источник отдаёт чистую таблицу или REST API без хитрой авторизации — Power Query решит задачу быстрее и без единой строки кода. VBA остаётся для случаев, когда нужна логика, ветвление, циклы по списку и нестандартный разбор.
Итог
VBA-парсинг строится из нескольких кирпичиков: HTTP-запрос (XMLHTTP или WinHttp), разбор ответа (строковые функции, RegExp или HTMLDocument), запись в ячейки и обработка ошибок. Освоив этот набор, можно автоматизировать сбор практически любых табличных данных прямо внутри привычной книги Excel.
Два классических сценария, на которых удобно тренироваться:
- Парсинг курсов валют — простой JSON/XML-источник, идеальный для первого парсера.
- Парсинг котировок акций — чуть сложнее: список тикеров, частые обновления, форматирование.
Оба разобраны в отдельных материалах — начните с того, что ближе к вашей задаче, а описанные здесь функции (GetResponse, ExtractJsonValue, SafeGet) будут общим фундаментом для обоих.