При интеграции 1С с веб-сервисами или загрузке данных со сторонних сайтов часто возникает задача получить содержимое определенного блока веб-страницы (например, <div id="main" class="newscontent">). После выполнения запроса через HTTPСоединение разработчик получает весь HTML-документ в виде одной большой строки. Ручной поиск подстрок и вырезание нужных фрагментов функциями работы со строками — процесс трудоемкий и нестабильный при малейшем изменении верстки. Разберем штатные и альтернативные инструменты платформы 1С, которые позволяют напрямую обращаться к нужным тегам и элементам страницы.
Самый правильный и платформенный способ извлечения данных из HTML без ручной строковой нарезки — построение дерева документа (DOM). Платформа 1С предоставляет специализированные объекты ЧтениеHTML и ПостроительDOM, которые берут на себя синтаксический разбор разметки.
Рассмотрим по шагам, как загрузить полученный HTML-текст в объектную модель и сразу извлечь узел по его идентификатору (id):
ЧтениеHTML и передаем в него строку с полученным документом.ПостроительDOM для создания объекта ДокументHTML.ПолучитьЭлементПоИдентификатору() для прямого доступа к тегу.Посмотрим на пример реализации данного алгоритма:
// Получаем HTML-код страницы
Соединение = Новый HTTPСоединение("example.com", 443,,, Новый ЗащищенноеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/pageview.php");
Ответ = Соединение.Получить(Запрос);
ТекстСтраницы = Ответ.ПолучитьТелоКакСтроку();
// Инициализируем чтение HTML
Чтение = Новый ЧтениеHTML;
Чтение.УстановитьСтроку(ТекстСтраницы);
// Строим DOM-дерево
Построитель = Новый ПостроительDOM;
ДокументHTML = Построитель.Прочитать(Чтение);
// Прямой доступ к элементу по id="main"
Элемент = ДокументHTML.ПолучитьЭлементПоИдентификатору("main");
Если Элемент <> Неопределено Тогда
// Получаем текстовое содержимое внутри тега
ТекстБлока = Элемент.ТекстовоеСодержимое;
// Получаем значение атрибута class
КлассЭлемента = "";
АтрибутКласс = Элемент.Атрибуты.ПолучитьИменованныйУзел("class");
Если АтрибутКласс <> Неопределено Тогда
КлассЭлемента = АтрибутКласс.Значение;
КонецЕсли;
КонецЕсли;
Если у целевого тега нет уникального идентификатора id, проанализируем выборку по имени тега с помощью метода ПолучитьЭлементыПоИмениТега(). Метод возвращает коллекцию СписокУзловDOM, по которой можно пройти циклом:
СписокДивов = ДокументHTML.ПолучитьЭлементыПоИмениТега("div");
Для Индекс = 0 По СписокДивов.Количество() - 1 Цикл
ТекущийЭлемент = СписокДивов.Получить(Индекс);
АтрибутКласс = ТекущийЭлемент.Атрибуты.ПолучитьИменованныйУзел("class");
Если АтрибутКласс <> Неопределено И АтрибутКласс.Значение = "newscontent" Тогда
ТекстНовостей = ТекущийЭлемент.ТекстовоеСодержимое;
Прервать;
КонецЕсли;
КонецЦикла;
Когда структура документа сложная, а искомый элемент находится глубоко во вложенности, эффективным решением становится язык выражений XPath. В платформе 1С результат разбора DOM поддерживает вычисление выражений XPath:
ВыражениеXPath = ДокументHTML.СоздатьВыражениеXPath("//div[@id='main' and @class='newscontent']", Неопределено);
РезультатXPath = ВыражениеXPath.Вычислить(ДокументHTML);
ЦелевойУзел = РезультатXPath.ПолучитьСледующий();
Если ЦелевойУзел <> Неопределено Тогда
Содержимое = ЦелевойУзел.ТекстовоеСодержимое;
КонецЕсли;
Важно: Не пытайтесь разбирать произвольный HTML с помощью объекта ЧтениеXML или пакетов XDTO. В отличие от строгого XML, реальная HTML-разметка страниц часто содержит незакрытые теги (<br>, <img>, <input>) и неэкранированные спецсимволы, что вызовет исключение при попытке чтения через XML-парсер.
Если разметка на целевом сайте имеет критические ошибки синтаксиса и штатный ПостроительDOM не может корректно разобрать дерево, на платформе под управлением ОС Windows можно воспользоваться встроенным движком MSHTML через COM-соединение. Он максимально толерантен к ошибкам верстки:
HTMLДокумент = Новый COMОбъект("htmlfile");
HTMLДокумент.Open();
HTMLДокумент.Write(ТекстСтраницы);
HTMLДокумент.Close();
Элемент = HTMLДокумент.getElementById("main");
Если Элемент <> Неопределено Тогда
ТекстБлока = Элемент.innerText;
ВнутреннийHTML = Элемент.innerHTML;
КонецЕсли;
Обратите внимание: COM-объекты доступны только в среде Windows. Если сервер 1С работает под управлением Linux или в 64-разрядном кластере без соответствующих 32/64-битных библиотек, данный способ применять не следует.
Если из всего ответа сервера нужно извлечь единственный конкретный фрагмент без построения полного объектного дерева документа, можно использовать регулярные выражения:
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Global = Ложь;
RegExp.Pattern = "<div[^>]*\bid=[""']main[""'][^>]*>([\s\S]*?)<\/div>";
Совпадения = RegExp.Execute(ТекстСтраницы);
Если Совпадения.Count > 0 Тогда
НайденныйФрагмент = Совпадения.Item(0).SubMatches.Item(0);
КонецЕсли;
Разберем распространенную ситуацию: современные веб-ресурсы часто строятся по принципу SPA (Single Page Application). В этом случае блок newscontent на стороне сервера пуст, а данные подгружаются скриптами в браузере. Выполняя запрос через HTTPСоединение, вы получите исходный шаблон без реального текста.
Для решения этой задачи откройте целевую страницу в браузере, запустите инструменты разработчика (клавиша F12) и перейдите на вкладку Сеть (Network). Найдите асинхронный XHR/Fetch-запрос, которым браузер запрашивает данные. В большинстве случаев сервер отдает структурированный ответ в формате JSON. Отправив запрос к этому адресу напрямую из 1С, вы сможете разобрать ответ штатной функцией ПрочитатьJSON() без необходимости взаимодействовать с HTML-разметкой.