Как получить значение из HTML-элемента через COM-объект Internet Explorer в 1С

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

При автоматизации взаимодействия 1С с внешними веб-ресурсами программисты часто прибегают к использованию COM-объекта InternetExplorer.Application. Это позволяет программно открывать страницы, заполнять формы и считывать результаты. Однако структура современных сайтов бывает сложной, и добраться до конкретного текстового значения внутри вложенных таблиц и контейнеров div бывает непросто. В этой статье мы разберем, как эффективно находить нужные элементы и как избежать распространенной ошибки, когда элемент «не найден» из-за слишком быстрой работы кода.

Инициализация и получение доступа к документу

Для начала проанализируем процесс создания объекта и загрузки страницы. Чтобы начать работу с HTML-контентом, нам необходимо создать экземпляр браузера и дождаться загрузки целевого URL. Рассмотрим стандартный код инициализации:


IE_COMОбъект = Новый COMОбъект("InternetExplorer.Application");
IE_COMОбъект.Visible = Ложь; // Скрываем окно браузера
IE_COMОбъект.Navigate("https://example.com/page");

После вызова метода Navigate управление возвращается в 1С практически мгновенно. Однако сама страница в браузере еще не загружена. Если мы сразу попытаемся выполнить IE_COMОбъект.Document, мы можем получить ошибку или пустой объект. Поэтому первым шагом всегда является проверка готовности документа.

Проблема асинхронной загрузки и ReadyState

Выясним причину, по которой код может работать в режиме отладки, но выдавать ошибку «Неопределено» при обычном запуске. В режиме отладки программист делает паузу, просматривая переменные, и за это время браузер успевает загрузить страницу. При обычном выполнении 1С пытается найти элемент в еще не существующем DOM-дереве.

Для решения этой проблемы проанализируем ситуацию и внедрим цикл ожидания. Мы будем проверять состояние ReadyState. Значение 4 означает, что документ полностью загружен.


Пока IE_COMОбъект.ReadyState < 4 Цикл
    // Приостанавливаем выполнение, чтобы дать браузеру время
    // В управляемых формах используем обработчик ожидания,
    // в обычных или внешних обработках можно использовать небольшую паузу
    Предупреждение("Ожидание загрузки...", 1); 
КонецЦикла;

IE_doc = IE_COMОбъект.Document;

Важный нюанс: даже если ReadyState равен 4, данные могут подгружаться скриптами (AJAX) внутри страницы. В таких случаях рекомендуется искать конкретный элемент в цикле в течение нескольких секунд, пока он не появится в дереве.

Поиск элемента с помощью querySelector

Допустим, у нас есть сложная структура вложенности, как в примере автора:

<div id="cpasContent"> ... <td class="cpasrez"> Текст </td> ... </div>

Рассмотрим подробнее методы поиска. Использование последовательного перебора всех дочерних узлов (ChildNodes) крайне неудобно и ненадежно, так как любое изменение верстки сайта сломает ваш код. Вместо этого разберем по шагам использование современных CSS-селекторов через метод querySelector.

  1. Сначала находим родительский контейнер по его уникальному идентификатору: rez = IE_doc.getElementByID("cpasContent");.
  2. Внутри этого контейнера ищем нужный нам элемент по названию его класса. Для поиска по классу в querySelector используется точка перед именем класса.

// Находим элемент с классом cpasrez внутри блока cpasContent
ЦелевойЭлемент = rez.querySelector(".cpasrez");

Если ЦелевойЭлемент <> Неопределено Тогда
    РезультатТекст = ЦелевойЭлемент.innerText;
    Сообщить("Найден текст: " + РезультатТекст);
КонецЕсли;

Метод querySelector возвращает первый найденный элемент, соответствующий критерию. Если вам нужно получить список всех подобных элементов (например, все строки таблицы), используйте querySelectorAll, который вернет коллекцию объектов.

Разница между innerText и textContent

При получении данных из найденного узла мы можем использовать разные свойства. Посмотрим на их отличия:

Альтернативные способы поиска

Если метод querySelector недоступен (например, в старых версиях библиотек системы), проанализируем альтернативные варианты:

  1. getElementsByClassName: возвращает коллекцию всех элементов с указанным классом. Обратите внимание, что это массив, поэтому нужно обращаться к конкретному индексу.
    
    Элементы = rez.getElementsByClassName("cpasrez");
    Если Элементы.length > 0 Тогда
        НужныйТекст = Элементы.item(0).innerText;
    КонецЕсли;
    
  2. getElementsByTagName: полезно, если у элемента нет класса или ID. Можно получить все td и перебрать их в цикле, проверяя содержимое соседних ячеек.

Завершение работы и очистка памяти

Проанализируем критически важный аспект работы с COM-объектами. Internet Explorer — это отдельное приложение. Если вы просто очистите переменную в 1С (IE_COMОбъект = Неопределено;), процесс iexplore.exe может остаться висеть в памяти компьютера, потребляя ресурсы. При многократном запуске обработки это может привести к зависанию сервера или клиентской машины.

Всегда закрывайте приложение явно:


// После завершения всех манипуляций
IE_COMОбъект.Quit();
IE_COMОбъект = Неопределено;

Современный подход: встроенные средства 1С

Разберем ситуацию, когда использование тяжелого Internet Explorer не оправдано. Если сайт не требует выполнения сложного JavaScript для отображения данных, гораздо быстрее и стабильнее использовать связку HTTPСоединение и ПостроительDOM.


Соединение = Новый HTTPСоединение("example.com");
Запрос = Новый HTTPЗапрос("/page");
Ответ = Соединение.Получить(Запрос);

Если Ответ.КодСостояния = 200 Тогда
    ЧтениеHTML = Новый ЧтениеHTML;
    ЧтениеHTML.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
    
    ПостроительDOM = Новый ПостроительDOM;
    ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML);
    
    // Теперь можно работать с ДокументHTML методами 1С
КонецЕсли;

Этот метод работает в фоновых заданиях на сервере гораздо надежнее, чем COM-объект, так как не зависит от графической оболочки Windows и настроек безопасности браузера.

Подведем итог: для успешного извлечения данных через InternetExplorer.Application необходимо обеспечить полную загрузку страницы через проверку ReadyState, использовать селекторы querySelector для точного позиционирования и не забывать про вызов метода Quit() для корректного завершения сессии браузера.

← На главную