Что делать, когда методы объекта Поле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С:ITIL(ИТИЛ), 1С:ITILIUM, Управление IT-отделом 8 через интернет с любого устройства посредством браузера, увеличивая эффективность работы пользователей и снижая нагрузку на сервер. Быстрая инсталляция портала за пару часов, удобный и интуитивно понятный интерфейс и безопасность данных помогут упростить работу с порталом и ускорить выполнение бизнес-процессов компании.

128000 руб.

19.12.2023    3205    5    0    

11

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

Модуль "Подсистема интеграции AmoCRM с 1С" позволяет обеспечить единое информационное пространство, в котором пользователи могут эффективно управлять клиентской базой, следить за статусами сделок и поддерживать актуальность данных как в AmoCRM, так и в 1С.

60000 руб.

07.05.2019    35336    70    45    

30

Оптовая торговля Розничная торговля WEB-интеграция 1С:Управление торговлей 10 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Платные (руб)

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

57600 руб.

26.11.2024    2912    2    3    

5

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

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

36000 руб.

03.08.2020    19364    24    22    

20

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

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

24000 руб.

27.09.2024    4935    4    2    

5

WEB-интеграция Программист Бизнес-аналитик Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Оптовая торговля, дистрибуция, логистика ИТ-компания Платные (руб)

Модуль "Экспортер" — это расширение для 1С, предназначенное для автоматизации процессов выгрузки данных. Оно позволяет эффективно извлекать, преобразовывать и передавать данные из систем 1С в интеграционную платформу Spot2D. Подсистема упрощает настройку, снижает количество ручных операций и обеспечивает удобный контроль данных.

14400 руб.

20.12.2024    1162    7    2    

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