Как распарсить веб-страницу, динамически формируемую клиентским JavaScript, в 1С 8.3

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

В современной веб-разработке все чаще встречается подход Single Page Application (SPA), когда сервер отдает браузеру лишь пустой каркас страницы и тяжелый JavaScript-сценарий. Этот сценарий при выполнении на стороне клиента отправляет фоновые запросы, получает данные и динамически строит DOM-дерево страницы — формирует тексты, таблицы, гиперссылки и изображения.

Если мы попытаемся получить содержимое такой страницы классическим HTTP-запросом через HTTPСоединение в 1С или просто сохраним ее код, то в результате получим лишь стартовый скрипт-загрузчик. Полноценного HTML-кода с нужными нам данными там не будет. Выясним, как решить эту задачу средствами платформы 1С 8.3, используя как штатные инструменты, так и продвинутые методы интеграции.

Рассмотрим по шагам несколько эффективных методов решения этой проблемы: от встроенных механизмов платформы до интеграции с внешними инструментами автоматизации.


Метод 1. Использование встроенного Chromium в «Поле HTML документа» (Платформа 8.3.14+)

Начиная с версии платформы 1С 8.3.14, встроенный элемент управления Поле HTML документа на операционной системе Windows использует современный движок Chromium (ранее использовался устаревший Internet Explorer/Trident). Это дает нам возможность полноценно выполнять клиентские JS-скрипты любой сложности прямо внутри управляемой формы 1С.

Типичная ошибка: Пытаться скачать сырой HTML-текст через HTTP-запрос, а затем присвоить его свойству поля HTML-документа. В этом случае скрипты сайта упадут с ошибками, так как они попытаются загрузить вспомогательные файлы по относительным путям в локальной папке платформы 1С.

Правильный алгоритм действий:

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

Рассмотрим пример кода инициализации перехода:


&НаКлиенте
Процедура ЗагрузитьСайт(Команда)
    // Указываем адрес целевого динамического ресурса
    АдресРесурса = "https://golikov.dev/web/index.html"; 
    Элементы.СодержимоеСтраницы.Перейти(АдресРесурса);
КонецПроцедуры

Основная хитрость заключается в том, что парсить страницу нужно только после того, как JavaScript полностью отработает и сформирует итоговое DOM-дерево. Для этого мы должны использовать событие поля HTML-документа ДокументСформирован.

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


&НаКлиенте
Процедура СодержимоеСтраницыДокументСформирован(Элемент)
    
    // Получаем DOM-модель документа из поля HTML-дерева
    ДокументHTML = Элемент.Документ;
    
    // Получаем коллекцию всех тегов "а" (гиперссылок) на странице
    ВсеСсылки = ДокументHTML.getElementsByTagName("a");
    
    Для Каждого Ссылка Из ВсеСсылки Цикл
        // Извлекаем атрибут href
        АдресСсылки = Ссылка.getAttribute("href");
        
        Если ЗначениеЗаполнено(АдресСсылки) Тогда
            // Обрабатываем полученную ссылку по бизнес-логике вашей системы
            ОбработатьАдрес(АдресСсылки);
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьАдрес(ЗначениеСсылки)
    // Пример вывода в окно сообщений
    Сообщить("Найдена ссылка: " + ЗначениеСсылки);
КонецПроцедуры

В тех случаях, когда объектная модель 1С для работы с DOM кажется слишком громоздкой, мы можем внедрить и выполнить собственный JS-код прямо в контексте загруженной страницы с помощью метода eval:


&НаКлиенте
Процедура СодержимоеСтраницыДокументСформирован(Элемент)
    
    ОкноДокумента = Элемент.Документ.defaultView;
    
    // JS-скрипт соберет все ссылки в одну строку с разделителем "|"
    СценарийJS = "
    |var links = document.getElementsByTagName('a');
    |var result = [];
    |for (var i = 0; i < links.length; i++) {
    |    result.push(links[i].href);
    |}
    |result.join('|');
    |";
    
    СтрокаСсылок = ОкноДокумента.eval(СценарийJS);
    МассивСсылок = СтрРазделить(СтрокаСсылок, "|");
    
    Для Каждого Ссылка Из МассивСсылок Цикл
        Сообщить("JS Нашел: " + Ссылка);
    КонецЦикла;
    
КонецПроцедуры

Метод 2. Исследование скрытого API сайта (Наиболее надежный и быстрый путь)

Даже если сайт защищен, а клиентский скрипт обфусцирован, сам браузер пользователя все равно общается с сервером по стандартным протоколам. Скрипт запрашивает данные с сервера (чаще всего в формате JSON) и только потом отрисовывает их в браузере.

Вместо того чтобы эмулировать браузер и выполнять тяжелые скрипты рендеринга, мы можем перехватить эти запросы и отправлять их напрямую из 1С.

Выполним следующие шаги для анализа сайта:

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

После того как структура запроса станет понятна, мы можем воссоздать этот запрос средствами 1С. Посмотрим на пример реализации HTTP-запроса к скрытому API сайта:


&НаСервере
Процедура ПолучитьДанныеЧерезAPI()
    
    // Настраиваем защищенное соединение
    ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
    
    // Указываем хост и создаем HTTP-соединение
    Соединение = Новый HTTPСоединение("api.targetsite.com", , , , , 15, ЗащищенноеСоединение);
    
    // Формируем запрос к эндпоинту, который возвращает нужные данные
    Запрос = Новый HTTPЗапрос("/v1/catalog/products?page=1");
    
    // Обязательно эмулируем заголовки браузера, чтобы сервер не заблокировал запрос
    Запрос.Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
    Запрос.Заголовки.Вставить("Accept", "application/json");
    
    Попытка
        Ответ = Соединение.Получить(Запрос);
        
        Если Ответ.КодСостояния = 200 Тогда
            СтрокаJSON = Ответ.ПолучитьТелоКакСтроку();
            
            // Парсим готовый структурированный JSON в структуру 1С
            ЧтениеJSON = Новый ЧтениеJSON;
            ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
            Данные = ПрочитатьJSON(ЧтениеJSON);
            ЧтениеJSON.Закрыть();
            
            // Обрабатываем полученные данные
            Для Каждого Товар Из Данные.products Цикл
                Сообщить(Товар.name + " - " + Товар.url);
            КонецЦикла;
        Иначе
            Сообщить("Ошибка сервера. Код ответа: " + Ответ.КодСостояния);
        EndIf;
    Исключение
        Сообщить("Не удалось выполнить запрос: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Преимущества данного метода: Скорость работы возрастает в десятки раз. Нам не нужно запускать графический интерфейс браузера, тратить память на рендеринг картинок и стилей. Мы получаем чистые данные напрямую.


Метод 3. Интеграция с безголовыми браузерами (Selenium / Playwright / Puppeteer)

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

Для автоматизации этого процесса часто применяются скрипты на языке Python с использованием библиотеки Selenium или Playwright. Они могут работать в фоновом (headless) режиме без вывода графического окна на экран.

Разберем схему интеграции 1С с внешним Python-скриптом:

  1. Скрипт на Python запускает браузер, переходит по URL-адресу, дожидается рендеринга страницы, собирает все ссылки и сохраняет их в JSON-файл на диске.
  2. 1С запускает выполнение Python-скрипта через операционную систему и ожидает окончания его работы.
  3. 1С считывает полученный JSON-файл и обрабатывает ссылки.

Пример кода на Python (скрипт parser.py):


# Шаг 1. Скрипт запускает браузер в фоновом режиме
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import json

options = Options()
options.add_argument('--headless') # Фоновый режим
driver = webdriver.Chrome(options=options)

try:
    driver.get('https://example.com')
    # Дожидаемся отрисовки динамических элементов
    driver.implicitly_wait(10) 
    
    # Находим все теги "а"
    elements = driver.find_elements("tag name", "a")
    links = [el.get_attribute('href') for el in elements if el.get_attribute('href')]
    
    # Сохраняем в файл результатов
    with open('result.json', 'w', encoding='utf-8') as f:
        json.dump(links, f, ensure_ascii=False)
finally:
    driver.quit()

Код запуска и чтения результатов в модуле 1С:


&НаСервере
Процедура ВыполнитьПарсингЧерезPython()
    
    ПутьКСкрипту = """C:\Scrapers\parser.py""";
    ПутьКФайлуРезультатов = "C:\Scrapers\result.json";
    
    // Удаляем старый файл результатов перед запуском
    ФайлРезультатов = Новый Файл(ПутьКФайлуРезультатов);
    Если ФайлРезультатов.Существует() Тогда
        УдалитьФайлы(ПутьКФайлуРезультатов);
    КонецЕсли;
    
    // Запускаем интерпретатор Python и ждем завершения выполнения (третий параметр = Истина)
    КомандаЗапуска = "python " + ПутьКСкрипту;
    ЗапуститьПриложение(КомандаЗапуска, , Истина);
    
    // Считываем результат работы скрипта
    Если ФайлРезультатов.Существует() Тогда
        
        ЧтениеJSON = Новый ЧтениеJSON;
        ЧтениеJSON.ОткрытьФайл(ПутьКФайлуРезультатов);
        НайденныеСсылки = ПрочитатьJSON(ЧтениеJSON);
        ЧтениеJSON.Закрыть();
        
        Для Каждого Адрес Из НайденныеСсылки Цикл
            Сообщить("Успешно импортировано: " + Адрес);
        КонецЦикла;
        
    Иначе
        Сообщить("Ошибка: Скрипт парсинга не сформировал файл результатов.");
    КонецЕсли;
    
КонецПроцедуры

Метод 4. Креативное решение: Анализ сетевого трафика через прокси/логи веб-сервера

Рассмотрим нестандартный подход, предложенный участниками обсуждения. Если сайт имеет защиту от парсинга, но ссылки на целевые объекты жестко завязаны на имена динамически загружаемых картинок-превью (например, ссылка на страницу товара формируется из ID картинки 12345.jpg), мы можем использовать локальный веб-сервер в качестве проксирующего звена.

При таком подходе мы:

  1. Настраиваем локальный веб-сервер (например, Apache) для перенаправления трафика.
  2. Открываем сайт через браузер или через внутреннее поле HTML-документа 1С.
  3. Используем программную имитацию прокрутки страницы (скроллинг), чтобы заставить динамический скрипт сайта подгрузить "ленивые" (lazy-load) картинки-превью.
  4. Программно считываем лог-файл (access.log) локального сервера Apache, выдергивая имена загруженных графических файлов по регулярному выражению или простому поиску подстрок.
  5. Формируем итоговые URL-адреса на основе логов веб-сервера.

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


Резюме и рекомендации

Выбор оптимального инструмента зависит от сложности целевого веб-ресурса:

← На главную