gifts2017

xPath и парсинг сайтов

Опубликовал Дмитрий Пуник (faust1976) в раздел Программирование - Практика программирования

Процедура получения части HTML страницы с помощью XPath запроса.

В процессе анализа сайтов с помощью браузера Chrome часто обращал внимание на пункт меню "Copy XPath"

После нескольких попыток разобраться как же это реализовано в 1С, почти забил.

Но нашел пример использования для Экселя http://www.ozgrid.com/forum/showthread.php?t=183596

Приписал для 1С . Результат представляю на Ваш суд 

&НаКлиентеНаСервереБезКонтекста
Функция getXPathElement(sXPath, objElement ) 
	
     // Split the xpath statement
    лМассивХР = СтрЗаменить(sXPath, "/",Символы.ПС);
    лИндексНоды = СтрПолучитьСтроку(лМассивХР,1); //лИндексНоды
	Если Найти(лИндексНоды, "@id") > 0 Тогда
		лИмя = СтрЗаменить(лИндексНоды,"[","");
		лИмя = СтрЗаменить(лИмя,"]","");
		лИмя = СтрЗаменить(лИмя,"=",Символы.ПС);
		лИмя = СтрПолучитьСтроку(лИмя,2);
		лИмя = СтрЗаменить(лИмя,"""","");
		ЛobjElement = objElement.ПолучитьЭлементПоИдентификатору(лИмя); 
		лМассивХР = СокрЛП(СтрЗаменить(лМассивХР,СтрПолучитьСтроку(лМассивХР,1),""));
		лИндексНоды = СтрПолучитьСтроку(лМассивХР,1);
	Иначе 
		ЛobjElement = objElement;
	КонецЕсли;	
	
	If Not Найти(лИндексНоды, "[") > 0 Then
        sNodeName = лИндексНоды;
        lNodeIndex = 1;
    Else
        лИндексНоды = СтрЗаменить(лИндексНоды, "[",Символы.ПС);
		лИндексНоды = СтрЗаменить(лИндексНоды, "]",Символы.ПС);
		sNodeName =  СтрПолучитьСтроку(лИндексНоды,1);
        lNodeIndex = Число(СтрПолучитьСтроку(лИндексНоды,2));
    EndIf;
	sRestOfXPath ="";
	Для Сч =2 По СтрЧислоСтрок(лМассивХР) Цикл
		sRestOfXPath = sRestOfXPath + ?(Сч=2,"","/")+СтрПолучитьСтроку(лМассивХР,Сч);		
	КонецЦикла;
     
    getXPathElement = Неопределено;
	
	лСчЭлементов = 0;
    For lCount = 0 To ЛobjElement.ДочерниеУзлы.Количество() - 1 Цикл
        If ВРег(ЛobjElement.ДочерниеУзлы.Item(lCount).ИмяУзла) = ВРег(sNodeName) Then
			лСчЭлементов = лСчЭлементов + 1;
			If lNodeIndex = лСчЭлементов Then
                If sRestOfXPath = "" Then
                    getXPathElement = objElement.ДочерниеУзлы.Элемент(lCount);
					Прервать;
                Else
                    getXPathElement = getXPathElement(sRestOfXPath, ЛobjElement.ДочерниеУзлы.Элемент(lCount));
					Прервать;
                EndIf;
            EndIf;
        EndIf;
	КонецЦикла;
	Возврат getXPathElement;
КонецФункции

Публикую после тестирования в своей обработке (т.е. прошла боевую проверку).

Пользоваться оказалось очень удобно :

	ЧтениеHTML = Новый ЧтениеHTML;
	ЧтениеHTML.УстановитьСтроку(ОтветСервера);
	ПостроительDOM = Новый ПостроительDOM;
	ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML);
	
	// Соберем данные из оглавления каталога 
	СтрокаХР = "[@id="+""""+"ContentWrapper"+""""+"]/div[1]/div[1]/ul";
	лКаталог = getXPathElement(СтрокаХР, ДокументHTML);

ОтветСервера - Это чистый HTML, в моем случае полученный как ответ WinHttp.ResponseText

См. также

Подписаться Добавить вознаграждение

Комментарии

1. BigB (BigB) 21.10.14 10:56
А при чем тут XPath? То что Вы так назвали функцию? При этом?
С таким же успехом можно было бы назвать её "АдронныйКоллайдер" и заголовок у статьи сделать таким "Адронный коллайдер и парсинг сайтов".
У Вас здесь нет использования XPath. Это у Вас обычный закат солнца вручную.
А, ну да, не вручную, а с помощью функции.
2. Дмитрий Пуник (faust1976) 21.10.14 11:42
Если я что то не понимаю вы исправьте .
Функцию назвал так, потому что в браузере увидел такое название.
Если слово XPah для Вас является сакральным, примите мои извинения …
3. BigB (BigB) 21.10.14 12:06
(2) из заголовка я понял, что вы парсите сайты использую встроенные средства платформы для работы с XPath, но оказалась, что Вы просто так функцию назвали.
4. Дмитрий Пуник (faust1976) 21.10.14 12:25
Да. Именно так .
Т.к. не смог разобраться как использовать встроенные возможности платформы.
При попытке воспользоваться встроенными возможностями и строкой XPath полученной из браузера результат оказался нулевой
5. Алексей 1 (AlX0id) 22.10.14 10:09
(4) faust1976, Проблема в том, что XPath - это чуть больше, чем строка пути в хроме ))
https://ru.wikipedia.org/wiki/XPath
6. Алексей 1 (AlX0id) 22.10.14 10:16
И да - в 1С для HTML он не работает. К сожалению.
7. Дмитрий Иванчура (Dmitryiv) 22.10.14 10:28
(6) AlX0id, Отчего же не работатет. Работатет, если страница сформирована по всем правилам XHTML.
8. Алексей 1 (AlX0id) 22.10.14 11:41
(7) Dmitryiv,
Я к тому, что вот такой кусок кода работать не будет.
ЧтениеHTML = Новый ЧтениеHTML;
ЧтениеHTML.ОткрытьФайл(ИмяВременногоФайла);
ПостроительDOM = Новый ПостроительDOM;
ДокументDOM = ПостроительDOM.Прочитать(ЧтениеHTML);
		
Разыменователь = Новый РазыменовательПространствИменDOM(ДокументDOM);
Выражение = ДокументDOM.СоздатьВыражениеXPath("//a", Разыменователь);
...Показать Скрыть

Упадет на последней строке - из-за того, что построитель ДОМ на самом деле создаст объект типа ДокументHTML (что как по мне довольно странно), у которого нет метода СоздатьВыражениеXPath. Или я ошибаюсь и в случае "если страница сформирована по всем правилам XHTML" - будет наблюдаться другое поведение?
9. Дмитрий Пуник (faust1976) 22.10.14 12:32
Коллеги, к сожалению, когда нужно распарсить несколько сайтов, некогда разбираться какой сформирован по правилам XHTML, а какой нет. Решение должно быть простым и быстрым.
Вот скопировать строку из браузера и вставить в настройки – это быстро. И это будет работать какое то время
С теоритической точки зрения XPath действительно больше чем просто строка, но как говорил Дэн Сяопин «Не важно, какого цвета кошка, лишь бы она ловила мышей» А мыши не все серые, и не всегда мыши …

На сайте я не нашел работающих примеров которые помогли бы мне использовать строчку из браузера для поиска элементов в загруженной страничке HTML.
Если можете поделиться информацией как можно использовать метод СоздатьВыражениеXPath для поиска части страницы - пожалуйста поделитесь
10. Алексей 1 (AlX0id) 22.10.14 13:57
(9) faust1976,
Вероятно, подойдет вот это http://msdn.microsoft.com/en-us/library/aa926403.aspx. Но опять же,судя по отзывам из интернета, даже MSXML2.DOMDocument не очень-то хорошо переваривает HTML.

Не обижайтесь, но просто ваш инструмент - это не XPath, а просто перебор дерева DOM в соответствии с некоторым правилом. Говоря об XPath, хотелось бы видеть хотя бы функции contains, >, < и т.п.. Типа "//*[contains(name(),'C')]", например..
11. Дмитрий Пуник (faust1976) 22.10.14 14:06
Конечно же это не XPath ..
Просто когда я искал решение, то ключевыми словами для меня были : XPath,Запрос … т..д
Мне это помогло … хотелось бы что бы люди сталкивающиеся с подобными задачами находили ответ быстрее чем я .
Ну, а заголовок статьи можно считать провокационным маркетингом
Хотя написать движек XPath в 1С была крамольная мысль ;-)
Jorge272; BigB; +2 Ответить
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа