Comments 47
Полезно. Спасибо.
Отлично -> в избранное. Спасибо!
UFO just landed and posted this here
Лично я давным давно отказался от регулярок в своих парсерах в пользу DOM и Xpath. Это действительно удобный инструмент.
Вы можете применять его для парсинга любой html-страницы
Если она является валидным xhtml-документом.
UFO just landed and posted this here
UFO just landed and posted this here
загрузчик html достаточно сообразителен, чтобы исправить ошибки, поэтому валидность не имеет особого значения — можно парсить даже полный бред:
другое дело, что алгоритмы исправлений могут отличаться у разных библиотек и браузеров, давая на выходе разные деревья. например php, этот пример интерпретирует вот так:
$crazyHtml = 'd<dd';
$dom =new DomDocument();
$dom->loadHtml($crazyHtml);
echo $dom->saveHtml();
другое дело, что алгоритмы исправлений могут отличаться у разных библиотек и браузеров, давая на выходе разные деревья. например php, этот пример интерпретирует вот так:
PHP Warning: DOMDocument::loadHTML(): Couldn't find end of Start Tag dd in Entity, line: 1 in /tmp/a.php on line 3
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>d</p><dd></dd></body></html>
Также как SQL, xpath является декларативным языком программирования.Это не язык программирования, а язык запросов. Вы же CSS не считаете языком программирования?
SQL, кстати, тоже языком программирования не является.
SQL с некоторыми модификациями, между прочим, Тьюринг-полный. А значит, такой же язык программирования, как и php/java, etc. Хотя в базовой версии, согласен, не совсем.
Спасибо
исправил
исправил
А языки запросов — это не языки программирования? Почему?
Я знакомство с XPath начинал отсюда zvon.org/xxl/XPathTutorial/General_rus/examples.html
А вообще очень классный язык. А для любителей парсить HTML регулярками — вот stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags#answer-1732454
Кстати, про оси навигации тоже полезно почитать.
И еще момент — можно XPath запросы прямо из FireBug консоли напрямую делать через функцию $x например $x("//a/@href");
А вообще очень классный язык. А для любителей парсить HTML регулярками — вот stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags#answer-1732454
Кстати, про оси навигации тоже полезно почитать.
И еще момент — можно XPath запросы прямо из FireBug консоли напрямую делать через функцию $x например $x("//a/@href");
спс за tidy и список функций — в избранное
После 5ти лет работы с xsl-шаблонами, строки типа ".//*[@id='w3c_home_upcoming_events']/ul/li[1]/div[2]/p[1]/a" уже не удивляют :)
>Старайтесь отказаться от регулярных выражений при парсинге веб-страниц в пользу xpath.
>Это сделает ваш код проще, понятнее. Вы допустите меньше ошибок. Сократиться время отладки.
Допустим у меня есть такой узел Numbers, я хочу заменить его на Количество
Примитивнейше регулярное выражение, а как это сделать при помощи Xpath, ну хотя бы концептуально?
>Это сделает ваш код проще, понятнее. Вы допустите меньше ошибок. Сократиться время отладки.
Допустим у меня есть такой узел Numbers, я хочу заменить его на Количество
Примитивнейше регулярное выражение, а как это сделать при помощи Xpath, ну хотя бы концептуально?
Важное замечание к топику — если вы разбираете DOM дерево средствами PHP(или другого языка), то такой инструмент как FirePath — не лучший помошник, ибо он показывает код, уже адаптированный WebKitом.
В свою очередь я делал это так:
PHP(Curl)->Tidy->сохранял в виде файла. Файл открывал чем-нибудь типа SketchPath и оттуда брал готовый XPath.
В свою очередь я делал это так:
PHP(Curl)->Tidy->сохранял в виде файла. Файл открывал чем-нибудь типа SketchPath и оттуда брал готовый XPath.
Общий совет: не надо использоваться в xpath запросах конструкцию
//
без лишней надобности. Это неэффективно: запрос пройдет *весь* DOM, в поисках удовлетворяющих условиям элементов. Потрудитесь указать полный путь до элемента (ну или хотя бы путь до области где могут быть эти элементы), это поможет вам сэкономить нервы и время на больших объемах данных.попробуйте SAXparser при работе с большими объемами. Так вы сэкономите не только свое время но и ресурсы сервера.
Разные вещи. Мне нужен DOM, SAX-пасеры тут не помогут.
ru.wikipedia.org/wiki/SAX
Применяются SAX-парсеры… для чтения XML-потоков большого объема (когда построение DOM требует слишком большого объема памяти).
Применяются SAX-парсеры… для чтения XML-потоков большого объема (когда построение DOM требует слишком большого объема памяти).
Я знаю что такое SAX, поэтому и говорю, что разные вещи.
Смысл в том, xpath-конструкция
Смысл в том, xpath-конструкция
//
неэффективна, и применять ее повсеместно вместо указания пути к элементу не рекомендуется.это мнимая эффектность.
Да по полному пути элемент будет найден быстрее, но это мили секунды! DOM дерево в оперативной памяти и поиск по нему осуществляется очень быстро, даже если мы не укажем полный путь.
Не достаток «полного пути» — в том что эта длинная цепочка узлов сделает ваш запрос плохо читаемым. Увеличивается вероятность допустить ошибку с Вашей стороны и программисту который получит это запрос после вас будет сложнее в нем разобраться.
Да по полному пути элемент будет найден быстрее, но это мили секунды! DOM дерево в оперативной памяти и поиск по нему осуществляется очень быстро, даже если мы не укажем полный путь.
Не достаток «полного пути» — в том что эта длинная цепочка узлов сделает ваш запрос плохо читаемым. Увеличивается вероятность допустить ошибку с Вашей стороны и программисту который получит это запрос после вас будет сложнее в нем разобраться.
Согласен, но есть различия при использовании XPath для парсинга сгенерированного XML какого-нибудь API и парсинга HTML сайта — в первом случае глубина дерева обычно гораздо меньше, соответственно xpath от корня гораздо короче. А когда нужно парсить сайты, то XPath от корня проще поломать незначительными изменениями в верстке.
Еще гораздо более простая и полезная оптимизация — если нужно парсить, допустим, статью и комментарии на хабре, а все остальное (облако тегов, похожие топики) нет, то можно сперва выбрать DIV содержащий И комментарии И статью (для хабра
На примере lxml питона:
Еще гораздо более простая и полезная оптимизация — если нужно парсить, допустим, статью и комментарии на хабре, а все остальное (облако тегов, похожие топики) нет, то можно сперва выбрать DIV содержащий И комментарии И статью (для хабра
//div[@id='main-content']
), сохранить в переменную языка программирования и потом уже искать запросами в этом контексте.На примере lxml питона:
context=document.xpath("//div[@id='main-content']")[0]
article_title=context.xpath("div[@class='hentry']/h2/span")
article_content=context.xpath("div[@class='hentry']/div[@class='content']")
comments=context.xpath("div[@id='comments']/ul")
В качестве альтернативы (и дополнения) к Firepath я так же использую Firefinder
Когда уже люди перестану писать бред типа $_res и поймут что вместо конкатенации достаточно перечисления аргументов echo через запятую…
xPath — действительно замечательная вещь, давно её использую!
Хотелось бы поделиться информацией об xPath в MySQL, с недавнего времени активно использую в одном проекте, работает чудесным образом и очень шустро. Работа с xml деревьями в MySQL поддерживается с версии 5.1 и выше.
Работать с XML можно посредствам двух функций:
Пример:
хотя, можно и так:
Поражает скорость выборки данным методом:
Даю ссылки, где можно можно более подробнее с этим ознакомиться и посмотреть примеры:
http://adw0rd.ru/2009/xpath-mysql/
и официальный док http://dev.mysql.com/doc/refman/5.1/en/xml-functions.html
Хотелось бы поделиться информацией об xPath в MySQL, с недавнего времени активно использую в одном проекте, работает чудесным образом и очень шустро. Работа с xml деревьями в MySQL поддерживается с версии 5.1 и выше.
Работать с XML можно посредствам двух функций:
ExtractValue()
и UpdateXML()
Пример:
SELECT * FROM taxonomy WHERE EXTRACTVALUE(`cluster`,'/sys-cluster/meta/title[self:text()]') = 'products';
хотя, можно и так:
SELECT * FROM taxonomy WHERE EXTRACTVALUE(`cluster`,'/sys-cluster/meta/title') = 'products';
Поражает скорость выборки данным методом:
mysql> SELECT benchmark(1000000, ExtractValue(@xml, '/a/b/c'));
+--------------------------------------------------+
| benchmark(1000000, ExtractValue(@xml, '/a/b/c')) |
+--------------------------------------------------+
| 0 |
+--------------------------------------------------+
1 row IN SET (4.77 sec)
Даю ссылки, где можно можно более подробнее с этим ознакомиться и посмотреть примеры:
http://adw0rd.ru/2009/xpath-mysql/
и официальный док http://dev.mysql.com/doc/refman/5.1/en/xml-functions.html
А индекс по XPath не умеет делать? Если нет, то не очень юзабельно ИМХО. (По крайней мере слышал, что в MSSQL индексы по полям XML поля можно строить, сам не щупал)
Хабралюди, помогите получить 4 кармы, есть интереснейшие посты по MySQL и PHP, уже подготовил, но нет возможности запостить. По XPath в том числе. Большое спасибо тем, кто откликнется. Прошу прощения за частичный офтоп.
Как раз появилась задача парсинга HTML страницы как XML документа и ваша статья очень пригодилась. Спасибо!
Спасибо, отличная статья. Но как быть с кодировкой? страница — в UTF-8, locale системы — UTF-8, на выходе — белиберда :(
Какая кодировка у файла скрипта на выходе которого белиберда?
UTF-8. Проблема решена простым хаком, найденным на странице документации в комментариях: $doc->loadHTML('<?xml encoding=«UTF-8»>'. $html); Это есть баг…
Существует программа паук позволяющая обработать все странички сайта и применить к каждой страничке набор XPath выражений.
Там же в ней есть сразу и возможность протестировать XPath выражения
http://dirs.info/spider/
Там же в ней есть сразу и возможность протестировать XPath выражения
http://dirs.info/spider/
Sign up to leave a comment.
Примеры xpath-запросов к html