Очистка HTML с XPath за один запуск - PullRequest
1 голос
/ 20 декабря 2011

Я очищаю сайт от определенных фрагментов информации.Кусок HTML, который я ищу, выглядит следующим образом:

1. <div class="data">
2.   <a class="anchor" name="123"></a>
3.   <a class="image_link" id="image_id" href="http:/link1">
4.     <img class="mainimg" id="456" src="http://link2" alt="description" title="title" >
5.   </a>
6. </div>

На веб-странице, конечно, много таких <div class="data">, и я хочу просмотреть все из них для получения следующей информации:

  • name = 123 (из строки 2)
  • href = link1 (из строки 3)
  • src = http://link2, alt = описание (из строки 4)

Я могу сделать это, но используя 3 различных выражения xPath, например:

Object[] o1 = node.evaluateXPath("//div[@class='data']/a/img");
Object[] o2 = node.evaluateXPath("//div[@class='data']/a[@class='image_link']");
Object[] o3 = node.evaluateXPath("//div[@class='data']/a[@class='anchor']");

, а затем получаю каждый атрибут, например:

((TagNode)o1[i]).getAttributeByName("src");

Это работает, но я перебираю одни и те же данные HTML 3 раза и в итоге получаю 3 разные и отдельные структуры данных с необходимой мне информацией.

Как я могу оптимизировать это, используя только одно выражение xpath?Спасибо.

1 Ответ

0 голосов
/ 20 декабря 2011

Возьмите объединение двух выражений:

//div[@class='data']/a/img/@*[name()='src' or name()='alt'] |
//div[@class='data']/a/@*[(parent::*/@class='image_link' and name()='href') or
                          (parent::*/@class='anchor' and name()='name')]

Вы также можете избежать уродства parent::*, разделив второе выражение на два:

//div[@class='data']/a/img/@*[name()='src' or name()='alt'] |
//div[@class='data']/a[@class='image_link']/@href |
//div[@class='data']/a[@class='anchor']/@name

Любой из них возвращает набор узлов, содержащий только узлы атрибутов. Вам все еще нужно будет перебрать эти узлы Выполните XPath в Java следующим образом (где expression является одним из двух приведенных выше):

NodeList node = (NodeList) xpath.evaluate(expression, doc, 
        XPathConstants.NODESET);
for (int i = 0; i < node.getLength(); i++) {
    Node attr = node.item(i);
    System.out.println(attr.getNodeName() + ": " + attr.getNodeValue());
}

Выход:

name: 123
href: http:/link1
alt: description
src: http://link2

Редактировать : Я только что заметил, что ваш пример кода ссылается на TagNode, поэтому я подозреваю, что вы действительно используете HTMLCleaner. Вы можете попытаться оценить XPath, используя встроенные методы HTMLCleaner, но он (очевидно) не является совместимым процессором XPath, поэтому результат непредсказуем. См. этот пост , чтобы узнать, как сначала превратить результат HTMLCleaner в W3C DOM Document и оценить XPath, используя стандартные методы Java:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...