Что делать, когда методы объекта ПолеHTMLДокумента.Документ (УФ) недоступны?

27.02.23

Интеграция - WEB-интеграция

Начиная с версии 8.3.14 некорректно загружаются некоторые веб-страницы в поле HTML-документа на УФ - методы ПолеHTMLДокумента.Документ недоступны. Методом "научного втыка" удалось обойти этот глюк системы.

"Удалось обойти" - быть может это громко заявлено, но, в моем случае, страницы начали грузиться правильно, методы документа отрабатываются в полном объеме. Этому я и хочу посвятить коротенькую статью, включив в нее все необходимые алгоритмы. Пробуйте, если и у вас есть такая проблема...

Итак, для меня все страницы разделились на две категории - хорошие и плохие. Хорошие отрабатывали все методы документа (один из них использую для разделения страниц по категориям), плохие - ничего не делали, лишь генерировали кучу ошибок там, где их не было до перехода на платформу 8.3.14. Если кто-то думает, что ошибки, возможно, ушли с обновлениями, - увы, нет. Платформа 8.3.22 показала такой же результат.

Собственно, самих алгоритмов немного, в комментариях они вряд ли нуждаются. Основные действия происходят в событии HTMLДокументСформирован:

 

&НаКлиенте
Процедура HTMLДокументСформирован(Элемент)

	Документ = Элемент.Документ;
	Если Документ.readyState <> "complete" Тогда
		Возврат;
	КонецЕсли;
	
	Если ЭтоПлохаяСтраница() Тогда
		//	Этот фрагмент должен выполниться один раз и следует предпринять
		//	дополнительные шаги во избежание зацикливания вызова HTMLДокументСформирован()
		СтруктураURI = НаКлиенте.СтруктураURI(АдресРесурса);
		Результат = GetКакТекст(АдресРесурса);
		Результат = СтрЗаменить(Результат, "<head>", "<head><base href=""" + СтруктураURI.База + """>");
		HTML = Результат;
		Возврат;
	КонецЕсли;
	
	// прочие алгоритмы
	
КонецПроцедуры



&НаКлиенте
Функция ЭтоПлохаяСтраница()
	
	Попытка
		Получены = Элементы.HTML.Документ.querySelector("html");
		Возврат Ложь;
	Исключение
		Возврат Истина;
	КонецПопытки;
	
КонецФункции


&НаКлиенте
Функция СтруктураURI(Знач СтрокаURI)
		
	//	Выражение = <URI>
	//
	//	Левая скобка параметра = <
	//	Правая скобка параметра = >
	//	Шаблон имени = [А-ЯA-Z][-_ А-Яа-я0-9A-Za-z]*?
	//
	//	+-	<URI> = ^(?:<Схема>:)?(?:\/\/<Источник>)?<Путь>(?:\?<Запрос>)?(?:#<Фрагмент>)?
	//	++	<Схема> = ((?:[^:\/?#\n]+)?)
	//	+-	<Источник> = (?:<Логин>:<Пароль>@)?<Хост>(?::<Порт>)?
	//	++	<Путь> = ([^?#\n]*/?)
	//	++	<Запрос> = ([^#\n]*)
	//	++	<Фрагмент> = (.*)
	//	++	<Логин> = ([^\/?#@:\n]*)
	//	++	<Пароль> = ([^\/?#@:\n]*)
	//	++	<Хост> = ([^\/?#@:\n]*)
	//	++	<Порт> = ([^\/?#@:\n]*)


	idПорт = "([^\/?#@:\n]*)";
	idХост = "([^\/?#@:\n]*)";
	idПароль = "([^\/?#@:\n]*)";
	idЛогин = "([^\/?#@:\n]*)";
	idФрагмент = "(.*)";
	idЗапрос = "([^#\n]*)";
	idПуть = "([^?#\n]*/?)";
	idИсточник = "(?:" + idЛогин + ":" + idПароль + "@)?" + idХост + "(?::" + idПорт + ")?";
	idСхема = "((?:[^:\/?#\n]+)?)";
	idURI = "^(?:" + idСхема + ":)?(?:\/\/" + idИсточник + ")?" + idПуть + "(?:\?" + idЗапрос + ")?(?:#" + idФрагмент + ")?";
	idPattern = idURI;
		
	RegExp = Новый COMОбъект("VBScript.RegExp");
		
	RegExp.Multiline = Истина;
	RegExp.Global = Истина;
	RegExp.IgnoreCase = Истина;
	RegExp.Pattern = idPattern;
		
	Результат = Новый Структура;
	Найдено = RegExp.Execute(СтрокаURI);
	
	Если Найдено <> Неопределено  Тогда
		Стр = Найдено.Item(0);
		
		Результат.Вставить("Схема ", Нрег(Стр.SubMatches(0)));
		Результат.Вставить("Логин", Стр.SubMatches(1));
		Результат.Вставить("Пароль", Стр.SubMatches(2));
		Результат.Вставить("Хост", Стр.SubMatches(3));
		Результат.Вставить("Порт", Стр.SubMatches(4));
		Результат.Вставить("Путь", Стр.SubMatches(5));
		Результат.Вставить("Запрос", Стр.SubMatches(6));
		Результат.Вставить("Фрагмент", Стр.SubMatches(7));
	КонецЕсли;
	
	
	База = "";
	Если НЕ ПустаяСтрока(Результат.Схема) Тогда
		База = База + Результат.Схема + "://";
	КонецЕсли;
	Если НЕ ПустаяСтрока(Результат.Логин) Тогда
		База = База + Результат.Логин + ":" + Результат.Пароль + "@";
	КонецЕсли;
	Если НЕ ПустаяСтрока(Результат.Хост) Тогда
		База = База + Результат.Хост;
	КонецЕсли;
	Если НЕ ПустаяСтрока(Результат.Порт) Тогда
		База = База + ":" + Результат.Порт;
	КонецЕсли;

	спПуть = СтрокаВМассив(Результат.Путь, "/");
	Индекс = спПуть.ВГраница();
	Файл = "";
	Если Индекс >= 0 Тогда
		Файл = спПуть[Индекс];
	КонецЕсли;
	
	спПуть = СтрокаВМассив(Файл, ".");
	Индекс = спПуть.ВГраница();
	Расширение = "";
	Если Индекс >= 1 Тогда
		Расширение = спПуть[Индекс];
	КонецЕсли;
	
	Каталог = База + Лев(Результат.Путь, СтрДлина(Результат.Путь)-СтрДлина(Файл));
	
	Результат.Вставить("База", База);
	Результат.Вставить("Каталог", Каталог);
	Результат.Вставить("Файл", Файл);
	Результат.Вставить("Расширение", Расширение);
	Результат.Вставить("URI", СтрокаURI);
	
    Возврат Результат;
 
КонецФункции


&НаСервереБезКонтекста
Функция GetКакТекст(URL)
	
	Возврат КоннекторHTTP.КакТекст(КоннекторHTTP.Get(URL));
	
КонецФункции


&НаКлиенте
Функция СтрокаВМассив(Знач Стр, Разделитель) Экспорт
	
	сп = Новый Массив;
	
	ДлинаРазделителя = СтрДлина(Разделитель);
	Если ДлинаРазделителя <> 0  Тогда
		Пока СтрДлина(Стр) > 0 Цикл
			Поз = Найти(Стр, Разделитель);
			Если Поз = 0 
			Тогда
				сп.Добавить(СокрЛП(Стр));
				Стр="";
			Иначе         
				сп.Добавить(СокрЛП(Лев(Стр, Поз-1)));
				Стр = СокрЛП(Сред(Стр, Поз+ДлинаРазделителя));
			КонецЕсли;
		КонецЦикла;
	Иначе
		ДлинаСтроки = СтрДлина(Стр);
		Для Инд = 1 По ДлинаСтроки Цикл
			сп.Добавить(Сред(Стр, Инд, 1));
		КонецЦикла;
	КонецЕсли;

	Возврат сп;	
	
КонецФункции

 

В приведенном алгоритме я все собрал до кучи, на клиенте - для демонстрации, не судите строго.

Использован КоннекторHTML Владимира Бондаревского для получения тела HTML-документа. При желании, замените чем-то другим.

 

Несколько дней спустя...

Дополнение: пытался сделать код более лаконичным. Когда страница сформирована, код HTML можно получить из документа, и тогда нет необходимости повторно загружать его с помощью КоннектораHTML (или каким-то другим способом). "Брюки превращаются...":

 


&НаКлиенте
Процедура HTMLДокументСформирован(Элемент)

	Документ = Элемент.Документ;
	Если Найти(Элемент.Документ.location.hash, "v8menu://") <> 0  Тогда
		HTML = "";
		Возврат
	КонецЕсли;
	
	Если Документ.readyState <> "complete" Тогда
		Возврат;
	КонецЕсли;
	
	Если ЭтоПлохаяСтраница() Тогда
		
		СтруктураURI = НаКлиенте.СтруктураURI(АдресРесурса);
		КодHTML = Документ.documentElement.outerHTML;
		КодHTML = СтрЗаменить(КодHTML, "<head>", "<head><base href=""" + СтруктураURI.База + """>");
		HTML = КодHTML;
		Возврат;
		
	КонецЕсли;

	//  Далее код

КонецПроцедуры

 

Это! - не работает. Я сравнил полученный из документа код HTML с тем, что получаем, обратившись к КоннекторуHTML (альтернативная загрузка). Они - разные. Так что, попытка оптимизации кода привела к плачевному результату.

 

Напоследок, обращаюсь к тем редким читателям, которые ставят минус этой публикации, не пояснив почему. Мне, например, было важно, чтобы все страницы грузились в ПолеHTMLДокумента правильно, без ошибок. Среди них информационные ресурсы, очень интересные программистам. Вот хотя бы взять пример страницы Document  с описанием свойств и методов документа HTML. После загрузки страницы в ПолеHTMLДокумента, описанные в ней методы, увы, недоступны. Что очень печально.

Так что, если Вы, редкий читатель этой статьи (не претендующей на истину в последней инстанции), реально намного умнее меня и знаете, как решить обозначенную в статье проблему другими методами, более достойными высокого разума программиста, - поделитесь, пожалуйста, с нами этим знанием в комментариях. Я это только приветствую. Всегда полезно поучиться у "старших" товарищей... (пишу эти строки без какого-либо сарказма).

См. также

Сайты и интернет-магазины WEB-интеграция Системный администратор Программист Пользователь Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    17781    19    22    

16

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс 24. Разработка имеет двухстороннюю синхронизацию 1С и Bitrix24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (платформа начиная с 8.3.23). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    19845    13    17    

16

WEB-интеграция 8.3.8 Конфигурации 1cv8 Автомобили, автосервисы Беларусь Украина Россия Казахстан Управленческий учет Платные (руб)

Расширение предназначено для конфигурации "1С:Предприятие 8. Управление Автотранспортом. ПРОФ". Функционал модуля: 1. Заполнение регистров сведений по подсистеме "Мониторинг", а именно: события по мониторингу, координаты по мониторингу, пробег и расход по мониторингу, текущее местоположение ТС по мониторингу 2. Заполнение путевого листа: пробег по мониторингу, время выезда/заезда, табличная часть ГСМ, места стоянок по геозонам. 3. Отчеты по данным загруженным в регистры сведений. 4. Предусмотрена автоматическая загрузка данных в фоновом режиме (условия работы данной загрузке читайте в описании товара) Модуль работает без включенной константы по настройкам мониторинга. Модуль формы предоставляется с открытым кодом, общий модуль защищен. Любой заинтересованный пользователь, имеет возможность скачать демо-версию расширения.

22656 руб.

25.05.2021    14421    42    8    

18

WEB-интеграция Программист Руководитель проекта Платформа 1С v8.3 Конфигурации 1cv8 1С:Франчайзи, автоматизация бизнеса Платные (руб)

Расширение значительно упрощает написание API на 1С. Веб программисты получают простой и понятный доступ к 1С. Описание API создаётся автоматически и представляется в виде удобном как для человека, так и для программной обработки.

24000 руб.

27.09.2024    1169    1    0    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. user925427 126 27.02.23 23:49 Сейчас в теме
Дьявол, как обычно, в деталях. Суть решения, если не ошибаюсь, в этой строке: Результат = СтрЗаменить(Результат, "<head>", "<head><ba se href=""" + СтруктураURI.База + """>"); Очередная недокументированная особенность объекта 1С. Пока не столкнёшься, не узнаешь, на заметку взять стоит. Автору плюс за желание поделиться с сообществом.
2. romasna 325 28.02.23 10:25 Сейчас в теме
Оставьте свое сообщение