Извлечение информации веб-страницы на основе шаблона в Java

Прямо сейчас я использую Jsoup для извлечения определенной информации (не весь текст) из некоторых сторонних веб-страниц, я делаю это периодически. Это работает нормально до тех пор, пока HTML-код определенной веб-страницы не изменится, это изменение приведет к изменению существующего Java-кода, это утомительная задача, потому что эти веб-страницы меняются очень часто. Также требуется, чтобы программист исправил код Java. Вот пример HTML-кода моего интереса на веб-странице:

<div>
<p><strong>Score:</strong>2.5/5</p>
<p><strong>Director:</strong> Bryan Singer</p>
</div>
<div>some other info which I dont need</div>

Теперь вот что я хочу сделать, я хочу сохранить эту веб-страницу (файл HTML) локально и создать из нее шаблон, например:

<div>
<p><strong>Score:</strong>{MOVIE_RATING}</p>
<p><strong>Director:</strong>{MOVIE_DIRECTOR}</p>
</div>
<div>some other info which I dont need</div>

Наряду с фактическими URL-адресами веб-страниц эти шаблоны HTML будут входными данными для Java-программы, которая будет определять местоположение этих предопределенных ключевых слов (например, {MOVIE_RATING}, {MOVIE_DIRECTOR}) и извлекать значения из фактических веб-страниц.

Таким образом, мне не нужно было бы изменять программу Java каждый раз, когда веб-страница изменяется, я просто сохраню HTML-код веб-страницы и заменю данные этими ключевыми словами, а остальная программа позаботится об этом. Например, в будущем фактический HTML-код может выглядеть так:

<div>
<div><b>Rating:</b>**1/2</div>
<div><i>Director:</i>Singer, Bryan</div>
</div>

и соответствующий шаблон будет выглядеть так:

<div>
<div><b>Rating:</b>{MOVIE_RATING}</div>
<div><i>Director:</i>{MOVIE_DIRECTOR}</div>
</div>

Кроме того, создание таких шаблонов может быть сделано не программистом, а любым, кто может редактировать файл.

Теперь вопрос заключается в том, как я могу добиться этого на Java, и существует ли какой-либо существующий и лучший подход к этой проблеме?

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

6 ответов

Решение

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

  1. Шаблон, который вы описываете, на самом деле не является "шаблоном" в обычном смысле этого слова: установленный статический контент, который выгружается в вывод с кучей динамического контента, вставленного в него. Вместо этого это "обратный" шаблон - это шаблон синтаксического анализа, который отбрасывается и отбрасывается, оставляя нужные параметры для поиска.

  2. Поскольку ваши веб-страницы меняются регулярно, вы не хотите жестко кодировать контент для слишком точного анализа, а хотите "увеличить" его основные функции, делая минимум предположений. т.е. вы хотите зафиксировать буквальное соответствие ключевого текста, такого как "Rating:", и обрабатывать чередующуюся разметку, такую ​​как "<b/>" гораздо более гибким способом - игнорируя это и позволяя ему изменяться без поломок.

  3. Когда вы объединяете (1) и (2), вы можете дать результат любому имени, которое вам нравится, но ЭТО Синтаксический анализ с использованием регулярных выражений. т.е. шаблонный подход - это подход синтаксического анализа с использованием регулярного выражения - они являются одним и тем же. Вопрос в том, какую форму должно принимать регулярное выражение.

    3A. Если вы используете Java-кодирование для анализа, тогда очевидный ответ заключается в том, что формат регулярного выражения должен быть java.util.regex формат. Все остальное является бременем для разработки, "нестандартным" и его будет сложно поддерживать.

    3B. Если вы хотите использовать анализатор с поддержкой html, то jsoup - хорошее решение. Проблема в том, что вам нужно больше обработки текста и регулярных выражений и гибкость, чем обеспечивает jsoup. Кажется, что он слишком привязан к определенным тегам и структурам HTML и поэтому разрывается при изменении страниц.

    3C. Вы можете использовать гораздо более мощный синтаксический анализатор, управляемый грамматикой, такой как ANTLR - форма, вдохновленная backus-naur-грамматикой, используется для управления синтаксическим анализом, и генератор кода вставляется для обработки проанализированных данных. Здесь, грамматические выражения синтаксического анализа могут быть действительно очень мощными со сложными правилами того, как текст упорядочен на странице и как текстовые поля и значения связаны друг с другом. Мощность выше ваших требований, потому что вы не обрабатываете язык. И нельзя избежать того факта, что вам все еще нужно описать уродливые биты, которые нужно пропустить - такие как теги разметки и т. Д. И борьба с ANTLR впервые требует инвестиций в образование, прежде чем вы окупитесь производительностью.

    3D. Есть ли инструмент Java, который просто использует простой подход типа шаблона, чтобы дать простой ответ? Ну, поиск в Google не дает много надежды https://www.google.com/search?q=java%20template%20based%20parser&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla%3Aen-GB%3Aofficial&client=firefox-a. Я полагаю, что любая попытка создать такого зверя выродится либо в обычный синтаксический анализ регулярных выражений, либо в более сложный синтаксический анализ с грамматическим управлением, потому что основные требования к сопоставлению / игнорированию / замене текста приводят решение в этих направлениях. Все остальное было бы слишком просто, чтобы на самом деле работать. Извините за негативное мнение - оно просто отражает проблемное пространство.

Мой голос за (3А) - самое простое, мощное и гибкое решение ваших задач.

Здесь не совсем подход, основанный на шаблонах, но jsoup все еще может быть работоспособным решением, если вы просто экспортируете запросы Selector в файл конфигурации.

Ваш непрограммист даже не должен видеть HTML, просто обновите селекторы в файле конфигурации. Что-то вроде SelectorGadget облегчит выбор того, какой селектор будет фактически использоваться.

Как я могу добиться этого в Java, и есть ли какой-либо существующий и лучший подход к этой проблеме?

Шаблонный подход - это хороший подход. Вы привели все причины, почему в вашем вопросе.

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

<div>
<p><strong>Score:</strong>{MOVIE_RATING}</p>
<p><strong>Director:</strong>{MOVIE_DIRECTOR}</p>
</div>

По сути, вы будете использовать Jsoup для обработки ваших шаблонов. Затем, когда вы используете Jsoup для обработки веб-страниц, вы проверяете все обработанные шаблоны, чтобы увидеть, есть ли совпадение.

При совпадении с шаблоном вы найдете ключевые слова в обработанном шаблоне, а затем найдете соответствующие значения на обработанной веб-странице.

Да, это было бы много кодирования, и сложнее, чем указано в моем описании. Ваш Java-программист должен разбить это описание на более простые и простые задачи, пока он или она не сможет кодировать задачи.

Если веб-страница часто меняется, то вы, возможно, захотите ограничить свой поиск такими полями, как MOVIE_RATING, до наименьшей возможной части страницы и игнорировать все остальное. Есть две возможности: вы можете использовать регулярное выражение для каждого поля или использовать какой-то CSS-селектор. Я думаю, что любой из них будет работать, и любой "шаблон" может состоять из простого списка поисковых выражений, регулярных выражений или CSS, которые вы примените. Просто пролистайте список и извлеките то, что вы можете, и потерпите неудачу, если какое-то определенное поле не найдено, потому что страница изменилась.

Например, регулярное выражение может выглядеть так:

"Score:"(.)*[0-9]\.[0-9]\/[0-9]

(Я не проверял это.)

Или вы можете попробовать другой подход, используя то, что я бы назвал "правилами" вместо шаблонов: для каждой части информации, которая вам нужна на странице, вы можете определить выражение (я) jQuery, которое извлекает текст. Часто, когда изменение страницы невелико, одни и те же хорошо написанные выражения jQuery все равно дают те же результаты.

Затем вы можете использовать Jerry (jQuery в Java) с почти такими же выражениями для извлечения искомого текста. Так что речь идет не только о селекторах, но и о других методах jQuery для обхода / фильтрации дерева DOM.

Например, правило для некоторого текста Director будет (в виде sudo-java-jerry-code):

$.find("div#movie").find("div:nth-child(2)")....text();

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

Если вы OO человек, каждое правило может быть определено в его собственной реализации. Если вы отличный человек, вы можете даже переписать правила, когда это необходимо, без перекомпиляции вашего проекта и все еще в Java. И т.п.

Как видите, основная идея здесь состоит в том, чтобы определить правила, как найти ваш текст; и не соответствовать шаблонам, так как они могут быть хрупкими к незначительным изменениям - представьте, если между двумя элементами div был добавлен пробел:). В этом примере я использовал синтаксис, похожий на jQuery (на самом деле это синтаксис, похожий на Джерри, поскольку мы находимся в Java) для определения правил. Это только потому, что jQuery популярен и прост, а также известен вашему веб-разработчику; в конце вы можете определить свой собственный синтаксис (в зависимости от используемого вами инструмента синтаксического анализа): например, вы можете анализировать HTML-код в дереве DOM, а затем писать правила, используя ваши вспомогательные методы, как перемещать его в интересующее вас место. Джерри также дает вам доступ к нижележащему дереву DOM.

Надеюсь это поможет.

Я использовал следующий подход, чтобы сделать нечто подобное в моем личном проекте, который генерирует RSS-канал отсюда, ведущий сайт по недвижимости в Испании.

С помощью этого инструмента я нашел арендованное место, в котором я сейчас живу;-)

  1. Получить код HTML со страницы
  2. Преобразуйте HTML в XHTML. Я использовал эту библиотеку, я думаю, сегодня могут быть лучшие варианты
  3. Используйте XPath для навигации по XHTML к интересующей вас информации

Конечно, каждый раз, когда они меняют исходную страницу, вам придется менять выражение XPath. Другой подход, который я могу придумать - семантический анализ исходного HTML-кода - далеко выходит за рамки моих скромных навыков;-)

Другие вопросы по тегам