gifts2017

Преимущества XPath для парсинга HTML

Опубликовал Сергей Одинесников (monsta) в раздел Обмен - Интеграция с WEB

Парсинг HTML без регулярных выражений

Пост уважаемого Elisy о парсере сайтов для 1С:Предприятия заслуживает на мой взгляд большего внимания, в связи с чем решил написать о своем опыте парсинга HTML и о том, зачем для этого использовались компоненты ElisyNetBridge и HtmlAgilityPack.

Зачем это нужно?

XPath позволяет простым способом получить перечисления нужных элементов HTML страницы, например список популярных категорий товаров (вверху заглавной страницы Яндекс.Маркет) можно получить так:

Разделы = HAP.DocumentNode.SelectNodes("//ul[@class='b-flex-gridb-popular-categories']");

мы получим контейнер, хранящий объекты категорий


соответственно код

Подразделы = Разделы.get_Item(0).SelectNodes(".//a[@class='name']"); 
Для i = 0 По Подразделы.Count - 1 Цикл
	Раздел = СокрЛП(Подразделы.get_Item(i).InnerHtml);
	Ссылка = СокрЛП(Подразделы.get_Item(i).Attributes.get_Item(1).value); 
КонецЦикла;

Вернет названия и ссылки на все категории популярных товаров с заглавной страницы. Перейдя по ссылке категории и выполнив код

Для Каждого ЭлементНоды Из СписокНодРаздела Цикл
	HAP.LoadHtml(appIE.Document.documentElement.innerHTML);
	КонтейнерПроизводителей = HAP.DocumentNode.SelectNodes("//a[text()='Популярные']/preceding::div[1]");
	Производители = КонтейнерПроизводителей.get_Item(0).SelectNodes(".//li[@class='pop-vendors__vendor']"); 
	Для e = 0 По Производители.Count - 1 Цикл
		Сообщить("Производитель №" + СокрЛП(e + 1) + " " + СокрЛП(Производители.get_Item(e).InnerHtml)); 
	КонецЦикла; 
КонецЦикла;

Можно получить всех текущих производителей данной категории со ссылками на страницы с перечнем их товаров


Почему не RegEx?

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

Зачем HtmlAgilityPack?

XPath может работать только с валидным XML, каковым HTML страница в большинстве случаев не является, т. к. браузеры не требовательны к валидности XML - достаточно одного <br> и стандартные компоненты для работы с XPath просто не смогут загрузить документ для дальнейшей обработки.

Зачем ElisyNetBridge?

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

Как тестировать выражения XPath?

В состав HtmlAgilityPack входит HAP Explorer (на скриншоте), загрузив в него HTML исходной страницы можно тестировать различные выражения и смотреть полученные результаты. Правда бывает падает при сложных выражениях :)

Вроде бы все понятно, но…

К статье прикреплена обработка с примером использования ElisyNetBridge и HtmlAgilityPack. Прошу не судить строго за синтаксис XPath - перебор категорий популярных товаров сделан для примера, XPath предлагает широкие возможности для перебора нужных элементов, наверняка есть варианты получше.

Скачать файлы

Наименование Файл Версия Размер
ПарсерЯндексМаркет.epf 53
.epf 1,40Mb
06.08.14
53
.epf 1,40Mb Скачать

См. также

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

Комментарии

1. Сергей Карташев (Elisy) 08.08.14 05:28
Спасибо за статью-продолжение. Полезным, например, для меня было узнать про HAP Explorer. Думаю эта утилита сократит время на разработку XPath. Забавно также описание, почему нельзя использовать RegEx в мире Html со вставками вида <i>he an&#8203;*̶͑̾̾&#8203;̅ͫ͏̙̤g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨ</i>
2. Андрей Крутских (K_A_O) 12.08.14 11:48
Статья полезная. Вот только название плохое. Думал, разбор на языке 1С, даже открывать не хотел.
3. Сергей Одинесников (monsta) 20.09.14 00:31
(1) Можно использовать 1С альтернативу HAP Explorer от Yashazz http://infostart.ru/public/280340/ и статья у коллеги хорошая
4. Гость 19.10.14 17:50
Evaluation limitation

All unregistered versions (evaluation copies) of Elisy .Net Bridge component show a message box when first accessed from 1C:Enterprise.

All unregistered versions (evaluation copies) of Elisy LinqTo1C component support generation of up to 7 tables.
5. Василий Орлов (Bublik2011) 19.10.14 19:04
Сегодня только нашел альтернативное чтение Xpath Тоже неплохо читается

	xmlParser= новый COMОбъект("msxml2.domdocument.6.0"); 
	xmlParser.loadXML("<html> <body>    <div>Первый слой      <span>блок текста в первом слое</span>    </div>    <div>Второй слой</div>    <div>Третий слой      <span class='text'>первый блок в третьем слое</span>      <span class='text'>второй блок в третьем слое</span>      <span>третий блок в третьем слое</span>    </div>    <img />  </body></html>"); 
	responseCode = xmlParser.selectSingleNode("html/body/div").text;
	Сообщить(responseCode);

...Показать Скрыть
6. Сергей Одинесников (monsta) 19.10.14 19:16
Попробуйте один тег не закрывать и поймете зачем нужен HtmlAgilityPack
7. Василий Орлов (Bublik2011) 19.10.14 19:27
(6) monsta, Вы правы. Придется в таком случае обработать ошибку , ТипЗнч(responseCode)=Неопределено и дальше обрабатывать сайт,
очень хорошо описаны функции msxml2.domdocument.6.0
http://msdn.microsoft.com/ru-ru/library/System.Xml.XmlNode
8. Сергей Одинесников (monsta) 20.10.14 21:17
Уверяю вас, большинство страниц не содержит валидного html. Соответственно весь сайт будет ТипЗнч(responseCode)=Неопределено.
HtmlAgilityPack преобразует невалидный html в валидный xml. За ссылку спасибо.
9. Илья (husky) 27.10.14 10:22
Установите компоненту C:\Users\...\AppData\Local\Temp\\ElisyNetBridge.exe - не запускается обработка, вроде все установил, но все пишет установить компоненту.. Что делать?
10. Сергей Одинесников (monsta) 27.10.14 20:15
Попробуйте скачать необходимый компонент по ссылке
11. Василий Орлов (Bublik2011) 02.11.14 23:23
(9) husky, перейдите к этому файлику. Это архив с расширением exe. Распакуете, будет внутри искомое. После установки разочаруетесь.

Вот простоя связка
1) Bitrix ENV (Bitrix Environment for Windows) или посложнее - Denwer

2) Простой редактор PHP (Scite)

3) НЕтриальный и БЕЗограничений firepath-0.9.7-fx1.xpi (простой, понятный, Уверене, применяли FireBug, так вот FirePath 0.9.7 - отлично работает.

Поверили? Есть время попробовать?
Тогда a) ищем архивную версию Firefox firefox-portable-12-0-28432-en-setup.exe
б) firebug-1.9.2.xpi , с которым будет работать
в) и наконец-то firepath-0.9.7-fx1.xpi
г) запускаем firefox-portable под другим пользователем, чтобы настройки мозиллы остались нетронутыми

В прикрепленном файле этот архив с этими файлами есть.

Автору статьи, который утверждает, что Xpath дает преимущества при парсинге - огромное уважение за такой заголовок. Ну не правда-ли, лаконично и на скорую руку можно парсер сделать.

<?php

$xpath = new DOMXPath(conn("http://www.zava.ru/catalog104_1.shtml"));
 foreach($xpath->query(".//*[@class='goods_h1']/a") as $a)
                { 
                    echo $a->getAttribute('href').'';
                }

function conn($Urlf)
{
$ch=curl_init();
$dom = new DOMDocument();
        $DOM->validateOnParse = true;
        @$dom->loadHTML($html);
return $dom;
}



...Показать Скрыть
Прикрепленные файлы:
soft.zip
12. Илья (husky) 03.11.14 19:49
(11) Bublik2011, хочу попробовать, но можно по-подробнее описать пункты 1-3 (ну так чтобы для тупых) и что значит под другим пользователем? и самое главное зачем все это нужно?
13. Ийон Тихий (cool.vlad4) 03.11.14 20:45
добавлю свои 5 копеек. раньше использовал htmlagilitypack, и даже здесь на сайте советовал его. сейчас все больше использую csquery. как-то с css селекторами мне лично проще. тем более в большинстве случаев селектор тупо копируется из css на сайте прямо в браузере, того элемента, который нас интересует.
PS кстати что htmlagilitypack не покрывает всего множества xpath, что csquery не покрывает всех css селекторов. вот такая беда. но как правило можно просто переписать xpath либо селектор.
к htmlagilitypack также есть расширение fizzler + fizzlerex , которое добавляет css селекторы.

ps еще могу посоветовать restsharp . это библиотека http клиент, который из коробки может много чего. http://restsharp.org/ . я использую связку restsharp+csquery
14. Ийон Тихий (cool.vlad4) 03.11.14 20:49
еще по-оффтоплю. есть fiddler, про него многие знают. а к нему есть плагин http://www.chadsowald.com/software/fiddler-extension-request-to-code , с помощью которого генерируется код запроса. очень удобно при парсинге, где есть заморочки, типа авторизации или всяких ajax . можно получить код и его проанализировать, подправить и т.п.
15. Ийон Тихий (cool.vlad4) 03.11.14 21:02
(12) husky, советует firepath (это плагин к firefox для проверки xpath запросов прямо в браузере на странице) . у меня он тоже стоит. замечание по таблицам - firefox достраивает таблицы с тегом tbody(это делается как я понимаю согласно стандарту). так, что при написании xpath запросов лучше не использовать тег tbody. а второе совет - это использовать php в качестве языка парсинга. по мне так второй совет - сомнителен. уж лучше python, не нужен будет никакой ни denwer и иже прочее. на хабре целый фрэймворк был для python-а по парсингу сайтов описан. grab называется. http://grablib.org/ru/ а так этих библиотек по парсингу для python-a как грязи.
16. Сергей Ожерельев (Поручик) 10.11.14 09:25
Совсем без регулярных выражений не обойтись. Сейчас делаю проект, в котором есть разбор HTML. Сам html разбираю с помощью построителя DOM, а некоторые данные приходится выцеплять регулярными выражениями.
17. Сергей Одинесников (monsta) 10.11.14 20:21
Cам HTML парсить регулярками не комильфо. Про некоторые данные вопросов нет.
18. Василий Орлов (Bublik2011) 29.11.14 21:06
(12) husky, очень буду рад очень подробно все описать, если при ближайшей возможности смогу объявить xpath=Новый COMОбъект("V8.DOMXPath") . У меня есть скриншоты и тексты, на написание которых вдохновили посты habrahabr.ru про преимущества xpath.


Соглашусь в Вами, husky, про Elisy .Net Bridge надо в заголовке написать про ограничения. Очень неприятно, знаете, с уважением изучать тексты описаний методов AgilityPack и уже чуть позже понимать, что еще есть риски при использовании - какие-то ограничения и весьма неопределенная сумма за снятие ограничений , приобретение лицензии за подключение dll HtmlAgilityPack.
19. Василий Орлов (Bublik2011) 29.11.14 21:14
(15) cool.vlad4, я Вам доверяю, мне тоже п.1 нравится :) Захотелось перейти на grab . Буду рад узнать о том , что grab эффективнее и доступнее.
20. Andrey Ivanov (pomestnik) 23.12.14 13:36
А как конвертировать и сохранить html страницу в валидный xml, который можно будет уже спокойно обработать 1сным DOM'ом
нашел в справке метод, но XmlTextWriter где его взять в 1ске)

HtmlWeb..::..LoadHtmlAsXml Method (String, XmlTextWriter)
Loads an HTML document from an Internet resource and saves it to the specified XmlTextWriter.
public void LoadHtmlAsXml(
string htmlUrl,
XmlTextWriter writer
)


или на вход пустить текст html страницы, а на выходе получить валидный xml .
21. Олег Голубев (ollega) 16.11.16 14:19
Не подключается Elisy через ПодключитьВнешнююКомпоненту в вашей обработке.
Попытался через Новый ComОбъект но потом зависает на выполнении команд.
Естественно всё необходимое установил. Из вашей обработки только не устанавливается Elisy, из другого источника установил. NetFramework так же установил и т.д.
Стоит Window7 64x как у вас то работает?
23. Олег Голубев (ollega) 16.11.16 17:32
Наперезагружался, поиграл с правами и т.д. Таки заработало частично, но через ComОбъект. Но вот на строке assemblyBytes = net.CallStatic("System.Convert", "FromBase64String", ДвоичныеДанные);

Зависает, не продвигается дальше. Такое ощущение, что работает только на 32х разрядных системах
24. Сергей Смирнов (Serginio) 16.11.16 18:03
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа