Как прочитать и распарсить HTML-документ в 1С:Предприятие?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Разработка интеграций и автоматический сбор данных с веб-ресурсов (парсинг) — частая задача в практике программиста 1С — для этого есть парсер характеристик и изображений товаров. Это может быть проверка актуальности структуры сайта, импорт каталога товаров, мониторинг цен конкурентов или автоматический сбор контактов. Однако веб-страницы редко имеют идеальную структуру XML, а современный веб-дизайн активно использует динамическую генерацию контента с помощью JavaScript. В этой статье мы подробно разберем, какими встроенными и внешними инструментами располагает платформа 1С для работы с HTML-документами, и выберем оптимальный подход под ваши задачи.

Метод 1: Серверный парсинг статического HTML через ЧтениеHTML и ПостроительDOM

Если целевой сайт отдает готовый статический HTML-код при обычном HTTP-запросе, наилучшим решением будет использование встроенных объектных моделей 1С на сервере. В отличие от старого подхода с использованием COM-объекта InternetExplorer.Application, встроенные объекты 1С кроссплатформенны (работают и под Windows, и под Linux) и не требуют наличия стороннего ПО.

Рассмотрим по шагам процесс загрузки и разбора веб-страницы. Главное преимущество специализированного объекта ЧтениеHTML перед стандартным ЧтениеXML заключается в его «всеядности». Он устойчив к ошибкам верстки, автоматически закрывает незакрытые теги (такие как <br>, <img> или <li>) и принудительно приводит документ к валидному DOM-дереву.

Проанализируем пример кода для загрузки и чтения веб-страницы:


// Шаг 1. Выполняем HTTP-запрос для получения сырого HTML-кода страницы
Соединение = Новый HTTPСоединение("example.com", , , , , 15);
Запрос = Новый HTTPЗапрос("/navigation-page.html");
Ответ = Соединение.Получить(Запрос);

Если Ответ.КодСостояния = 200 Тогда
    СтрокаHTML = Ответ.ПолучитьТелоКакСтроку();
    
    // Шаг 2. Инициализируем специализированное чтение HTML
    ЧтениеHTML = Новый ЧтениеHTML;
    ЧтениеHTML.УстановитьСтроку(СтрокаHTML);
    
    // Шаг 3. Строим объектную модель документа (DOM)
    ПостроительDOM = Новый ПостроительDOM;
    ДокументDOM = ПостроительDOM.Прочитать(ЧтениеHTML);
    
    // Обязательно освобождаем ресурс чтения
    ЧтениеHTML.Закрыть();
    
    // Теперь у нас есть объект "ДокументDOM", готовый к анализу
Иначе
    ВызватьИсключение "Не удалось загрузить страницу. Код ответа: " + Ответ.КодСостояния;
КонецЕсли;

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

Метод 2: Быстрый поиск элементов с помощью языка запросов XPath

Рекурсивный обход дерева DOM вручную — процесс трудоемкий и медленный. Чтобы быстро выбрать из документа нужные элементы (например, пункты главного меню, ссылки или таблицы с данными), в платформе 1С реализована поддержка языка запросов XPath. Это позволяет выполнять точечные запросы к документу без необходимости писать сложные циклы.

Выясним, как отобрать все ссылки из главного меню сайта, если мы знаем, что меню обернуто в тег с классом main-menu. Разберем следующий пример:


// Выражение XPath для выбора всех тегов <a>, находящихся внутри контейнера с классом 'main-menu'
ВыражениеXPath = "//div[@class='main-menu']//a";

// Вычисляем выражение в контексте нашего DOM-документа
РезультатXPath = ДокументDOM.ВычислитьВыражениеXPath(ВыражениеXPath, ДокументDOM);

// Обходим полученный результат в цикле
УзелDOM = РезультатXPath.ПолучитьСледующий();
Пока УзелDOM <> Неопределено Цикл
    // Извлекаем текстовое содержимое ссылки (анкор)
    ТекстСсылки = СократитьЛП(УзелDOM.ТекстовоеСодержимое);
    
    // Получаем значение атрибута "href"
    АтрибутHref = УзелDOM.Атрибуты.ПолучитьИменованныйЭлемент("href");
    АдресСсылки = ?(АтрибутHref <> Неопределено, АтрибутHref.Значение, "");
    
    Если ЗначениеЗаполнено(ТекстСсылки) Тогда
        Сообщить("Элемент меню: " + ТекстСсылки + " -> Ссылка: " + АдресСсылки);
    КонецЕсли;
    
    УзелDOM = РезультатXPath.ПолучитьСледующий();
КонецЦикла;

Использование ВычислитьВыражениеXPath позволяет значительно сократить объем программного кода и увеличить скорость работы парсера за счет выполнения поиска на уровне платформенного C++ движка. Для этой задачи есть парсер цен конкурентов для 1С.

Метод 3: Использование клиентского элемента «Поле HTML-документа»

Если вам необходимо распарсить динамический сайт, контент которого формируется на стороне клиента с помощью JavaScript (например, SPA-приложения на React, Angular или Vue), обычный HTTP-запрос на сервере вернет лишь пустой шаблон страницы без данных. В этом случае на помощь приходит элемент управляемой формы Поле HTML-документа.

В современных версиях платформы 1С данный элемент использует современный движок Chromium (WebKit), что обеспечивает полноценное выполнение клиентских скриптов JS. Нам необходимо дождаться полной загрузки документа и обратиться к его объектной модели прямо «НаКлиенте».

Для реализации этого сценария выполним следующие действия по шагам:

  1. Создадим на управляемой форме реквизит с типом Строка (например, АдресСайта) и элемент формы с типом Поле HTML-документа (имя элемента — ПолеHTML).
  2. Свяжем элемент формы с реквизитом, содержащим URL.
  3. Создадим обработчик события элемента формы ДокументСформирован. Это критически важно, так как обращаться к DOM-модели можно только после того, как браузер полностью загрузит страницу и выполнит все стартовые скрипты JavaScript.

Посмотрим на пример кода в модуле управляемой формы:


&НаКлиенте
Процедура ЗагрузитьСайт(Команда)
    // Инициируем переход по ссылке в элементе формы
    Элементы.ПолеHTML.Документ.location.href = "https://example.com/dynamic-page";
КонецПроцедуры

&НаКлиенте
Процедура ПолеHTMLДокументСформирован(Элемент)
    // Документ полностью загружен, JS отработал. Получаем объектную модель
    ДокументHTML = Элемент.Документ;
    
    // Мы можем использовать стандартные JS-селекторы прямо из 1С!
    // Например, querySelectorAll для получения коллекции элементов по CSS-классу
    СписокЭлементов = ДокументHTML.querySelectorAll(".product-card-title");
    
    Для Индекс = 0 По СписокЭлементов.length - 1 Цикл
        ТекущийЭлемент = СписокЭлементов.item(Индекс);
        Сообщить("Найден товар: " + ТекущийЭлемент.innerText);
    КонецЦикла;
КонецПроцедуры

Важное ограничение: данный метод работает исключительно в интерактивном режиме на клиенте (&НаКлиенте). Он не может быть запущен в фоновом задании или на сервере без участия пользователя.

Метод 4: Серверный парсинг динамических сайтов через API (JSON)

Если вам требуется выполнять регламентный (автоматический) сбор данных с динамического сайта на сервере 1С ночью, клиентский элемент формы использовать не получится. Запуск полноценного безголового браузера (Headless Chrome через Selenium) из 1С — ресурсоемкая задача, требующая установки внешних утилит (например, Python или Node.js) на сервер.

Однако существует более элегантный и производительный путь. Проанализируем, как работают современные динамические сайты. Они не содержат данных в самом HTML-коде; они отправляют фоновые асинхронные запросы (XHR/Fetch) к своему внутреннему API и получают данные в чистом формате JSON, после чего отрисовывают их на экране.

Вместо того чтобы имитировать действия пользователя и пытаться отрисовать интерфейс, мы можем перехватить эти запросы:

  1. Откройте целевой сайт в браузере (например, Google Chrome).
  2. Нажмите клавишу F12 и перейдите на вкладку Network (Сеть).
  3. Выберите фильтр Fetch/XHR и обновите страницу.
  4. Найдите запрос, в ответе которого приходит JSON-структура с нужными вам данными (например, список товаров, структура меню или цены) — для получения этих данных есть парсер цен товаров в интернет-магазинах.
  5. Изучите URL-адрес запроса, его метод (GET/POST) и передаваемые заголовки (Headers) — в этом поможет утилита логирования и анализа HTTP-запросов для 1С.

Теперь мы можем повторить этот запрос напрямую из 1С, получив чистые данные без лишней разметки:


Соединение = Новый HTTPСоединение("api.example.com", , , , , 10);
Запрос = Новый HTTPЗапрос("/v1/navigation/menu");
Запрос.Заголовки.Вставить("Accept", "application/json");

Ответ = Соединение.Получить(Запрос);

Если Ответ.КодСостояния = 200 Тогда
    СтрокаJSON = Ответ.ПолучитьТелоКакСтроку();
    
    // Читаем JSON встроенным высокопроизводительным механизмом 1С
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(СтрокаJSON);
    
    ДанныеМеню = ПрочитатьJSON(Чтение);
    Чтение.Закрыть();
    
    // На выходе получаем соответствие или массив структур, готовый к обработке
    Для Каждого ПунктМеню Из ДанныеМеню.items Цикл
        Сообщить("Пункт меню: " + ПунктМеню.title + " -> Ссылка: " + ПунктМеню.url);
    КонецЦикла;
КонецЕсли;

Этот метод является наиболее стабильным, быстрым и экономным с точки зрения трафика и серверных ресурсов — для его реализации подойдёт загрузка номенклатуры по HTTP и JSON.

Метод 5: Использование внешних компонент и .NET (AngleSharp, HtmlAgilityPack)

В случаях, когда стандартных возможностей платформы 1С не хватает (например, при обработке гигантских объемов данных или при необходимости использовать сверхсложные CSS-селекторы прямо на сервере), разработчики прибегают к интеграции с проверенными библиотеками экосистемы .NET.

Такие библиотеки, как HtmlAgilityPack или AngleSharp, предоставляют мощнейшие инструменты для разбора «грязного» HTML и выполнения запросов к DOM со скоростью компилируемого кода. Подключение таких библиотек в 1С происходит через COM-объекты или специализированные мосты интеграции .NET.

Рассмотрим концептуальный пример работы с .NET-библиотекой через COM-обертку:


// Инициализируем обертку для работы с .NET сборками
ПоставщикСборок = Новый COMОбъект("Elisy.Net.Bridge.AssemblyProvider");
HtmlDocumentClass = ПоставщикСборок.Load("HtmlAgilityPack.dll").Create("HtmlAgilityPack.HtmlDocument");

// Загружаем HTML-текст в объект сборки
HtmlDocumentClass.LoadHtml(СтрокаHTML);

// Выполняем быстрый поиск по XPath средствами внешней библиотеки
Узлы = HtmlDocumentClass.DocumentNode.SelectNodes("//a[@class='menu-link']");
Если Узлы <> Неопределено Тогда
    Для Каждого Узел Из Узлы Цикл
        Сообщить(Узел.InnerText);
    КонецЦикла;
КонецЕсли;

Такой подход рекомендуется применять только в высоконагруженных проектах, где скорость обработки сотен тысяч страниц в секунду является критическим фактором.

Метод 6: Обход систем защиты и эмуляция браузера

Современные веб-ресурсы часто защищены от автоматического сбора данных системами фильтрации трафика (например, Cloudflare, DDoS-Guard). Если вы попытаетесь сделать простой запрос через HTTPСоединение без предварительной настройки, сервер, скорее всего, вернет ошибку 403 Forbidden или потребует разгадать капчу.

Для минимизации риска блокировки необходимо придерживаться следующих правил при формировании HTTPЗапроса в 1С:

  1. Подменяйте User-Agent. По умолчанию 1С отправляет заголовок, содержащий техническую информацию о платформе (например, 1C+Enterprise/8.3). Веб-серверы сразу распознают в этом робота. Устанавливайте заголовки реальных современных браузеров.
  2. Используйте прокси-серверы. При частом обращении к одному и тому же сайту с одного IP-адреса вас быстро заблокируют. Настройте ротацию прокси в параметрах HTTPСоединения.
  3. Передавайте Cookies. Некоторые сайты требуют сохранения сессии. Извлекайте заголовки Set-Cookie из ответов сервера и передавайте их в последующих запросах в заголовке Cookie.

Разберем пример правильной подготовки HTTP-запроса с эмуляцией заголовков:


// Установка параметров прокси-сервера (при необходимости)
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("http", "192.168.1.100", 8080, "ЛогинПрокси", "ПарольПрокси");

Соединение = Новый HTTPСоединение("example.com", , , , Прокси, 15);

Запрос = Новый HTTPЗапрос("/target-page");

// Заполняем обязательные заголовки для маскировки под реального пользователя
Запрос.Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
Запрос.Заголовки.Вставить("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
Запрос.Заголовки.Вставить("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7");
Запрос.Заголовки.Вставить("Cache-Control", "no-cache");

Ответ = Соединение.Получить(Запрос);

Подведем итоги

Мы рассмотрели ключевые механизмы работы с HTML-документами в экосистеме 1С:Предприятие 8.3. Подводя итог, можно дать следующие рекомендации по выбору технологии:

← На главную