Соскоб экрана: регулярные выражения или выражения XQuery? - PullRequest
6 голосов
/ 14 марта 2009

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

Мое решение было использовать выражение XQuery . Выражение было довольно длинным, потому что содержимое, которое мне было нужно, было довольно глубоко в иерархии HTML. Мне пришлось честно искать среди предков, прежде чем я нашел элемент с атрибутом id. Например, очистка страницы Amazon.com для измерений продукта выглядит следующим образом:

//a[@id="productDetails"]
/following-sibling::table
//h2[contains(child::text(), "Product Details")]
/following-sibling::div
//li
/b[contains(child::text(), "Product Dimensions:")]
/following-sibling::text()

Это довольно неприятное выражение, но именно поэтому Amazon предоставляет API веб-службы. Во всяком случае, это только один пример. Вопрос был не об Амазоне, а о соскобе экрана.

Интервьюеру не понравилось мое решение. Он думал, что это хрупко, потому что изменение в дизайне страницы Amazon может потребовать переписать выражение XQuery. Трудно отладить выражение XQuery, которое не совпадает ни с чем на странице, к которой он применяется.

Я не согласился с его заявлениями, но я не думал, что его решение улучшилось: он подумал, что лучше использовать регулярное выражение , и искать контент и разметку рядом с весом доставки. Например, используя Perl:

$html =~ m{<li>\s*<b>\s*Product Dimensions:\s*</b>\s*(.*?)</li>}s;

Мой контраргумент заключался в том, что Amazon также может изменить свой HTML-код. Они могут записывать теги HTML прописными буквами (<LI>), добавлять атрибуты CSS, изменять <b> на <span> или изменять метку «Размеры продукта:» на «Размеры:» или многие другие виды изменений. Моя точка зрения заключалась в том, что регулярные выражения не решают слабые места, которые он выявил в моем решении XQuery.

Но кроме того, регулярные выражения могут находить ложные срабатывания, если вы не добавите в выражение достаточно контекста. Он также может непреднамеренно соответствовать содержимому, которое находится внутри комментария, или в строке атрибута, или в разделе CDATA.

У меня вопрос, какую технологию вы используете для очистки экрана? Почему вы выбрали это решение? Есть ли веская причина для его использования? Или никогда не использовать другой? Есть ли третий вариант помимо тех, что я показал выше?

PS: Предположим, что нет API веб-службы или другого более прямого способа получения желаемого контента.

Ответы [ 8 ]

4 голосов
/ 14 марта 2009

Я бы использовал регулярное выражение, но только потому, что большинство HTML-страниц не являются допустимым XML, поэтому вы никогда не получите XQUERY для работы.

Я не знаю XQuery, но для меня это выглядит как выражение XPATH. Если это так, он выглядит немного дороже с таким количеством операторов "//".

3 голосов
/ 14 марта 2009

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

Ваш контраргумент пропускает момент, когда его решение было хрупким в отношении локальных изменений, в то время как ваше решение хрупко в отношении глобальных изменений. Все, что сломает его, вероятно, сломает ваше, но не наоборот.

Наконец, намного проще встроить slop / flex в его решение (если, например, вам приходится иметь дело с несколькими незначительными изменениями во входных данных).

2 голосов
/ 22 апреля 2009

Попробуйте JTidy или BeautifulSoup отлично работает для меня. конечно // Эксперимент XPATH довольно затратен.

1 голос
/ 30 декабря 2012

Для работы с html-страницами лучше всего использовать HTMLAgilityPack (и с некоторыми кодами Linq). Это отличный способ проанализировать все элементы и / или выполнить прямой поиск с помощью XPath. На мой взгляд, он более точен, чем RegEx, и его легче программировать. Я немного неохотно использовал его ранее, но его очень легко добавить в ваш проект, и я думаю, что он является стандартом де-фактора для работы с HTML. http://htmlagilitypack.codeplex.com/

Удачи!

1 голос
/ 23 января 2010

Регулярные выражения действительно быстрые и работают с не XML-документами. Это действительно хорошие моменты против XQuery. Тем не менее, я думаю, что использовать какой-то конвертер в XHTML, такой как аккуратный и, возможно, несколько более простой XQuery, как только последняя часть из вашего:

//b[contains(child::text(), "Product Dimensions:")]/following-sibling::text()

- очень хорошая альтернатива.

С уважением,

Рафал Русин

1 голос
/ 14 марта 2009

Не хрупкое решение для очистки экрана? Удачи интервьюеру в этом: то, что регулярные выражения отбрасывают много контекста, не означает, что они менее хрупкие: просто то, что они хрупки в других отношениях. Хрупкость может даже не быть недостатком: если что-то меняется на исходной веб-странице, вам часто будет лучше, если ваше решение вызывает тревогу, а не пытается компенсировать хитрым (и непредсказуемым) способом. Как вы заметили. Эти вещи всегда зависят от ваших предположений: в данном случае от того, что представляет собой вероятное изменение.

Мне очень нравится пакет agility : вы получаете терпимость к не-XHTML-совместимым веб-страницам в сочетании с выразительной мощью XPath.

1 голос
/ 14 марта 2009

Я на самом деле нахожу CSS-выражения для поиска легче, чем оба. Вероятно, существует по крайней мере одна библиотека на выбранном вами языке, которая будет анализировать страницу и позволять вам писать CSS-директивы для поиска определенных элементов. Если поблизости есть подходящий класс или хук идентификатора, то выражение довольно тривиально. В противном случае, возьмите элементы, которые кажутся подходящими, и повторите их, чтобы найти те, которые вам нужны.

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

1 голос
/ 14 марта 2009

Я использую BeautifulSoup для утилизации.

...