Jsoup: select() возвращает пустой, когда не должен

#java #css-selectors #html-parsing #jsoup

#java #css-селекторы #html-синтаксический анализ #jsoup

Вопрос:

Я пытаюсь выбрать информационное поле на странице ввода Google в Википедии: http://en.m.wikipedia.org/wiki/Google

Итак, я вызываю:

 contentDiv = document.select("div[id=content]").first();
  

Который работает, как и ожидалось, тогда я делаю:

 Elements infoboxes = contentDiv.select("table[class=infobox]");
  

Затем я проверяю infoboxes.isEmpty() , и я ошеломлен, обнаружив, что он пуст!

Я проверил и убедился, что элемент contentDiv содержит следующее:

 <table class="infobox vcard" style="width: 22em;" cellspacing="5">
  

Итак, почему contentDiv.select("table[class=infobox]") возвращает пустой???

ОБНОВЛЕНИЕ: я протестировал вышеуказанное, contentDiv.select("table[class=infobox vcard]") и оно отлично работает! Это странно, поскольку я знаю, что в отличие от table.infobox.vcard обозначения, которое выбирает только точный многоклассовый элемент, table[class=infobox] следует выбирать все таблицы, которые имеют по крайней мере infobox в их перечисленных классах.

Кстати, я протестировал код с другой записью в Википедии, содержащей:

 <table class="infobox biota" style="text-align: left; width: 200px; font-size: 100%;">
  

И это contentDiv.select("table[class=infobox]") ведет себя точно так, как ожидалось, возвращая этот элемент таблицы в качестве первого элемента infoboxes .

Есть идеи, почему несоответствие? Что может объяснить это странное поведение?

Возможно ли, что я просто наткнулся на ошибку Jsoup?

(Я использую jsoup-1.5.2, не последнюю версию, но мне не нужна поддержка HTML5, и по разным причинам я не могу сразу перейти на последнюю версию 1.6.1).

Ответ №1:

[attributename=attributevalue] Селектор точно соответствует. Это указано в спецификации селектора CSS (выделение мое):

[att=val]
Совпадение, когда значение атрибута элемента «att» точно равно «val».

Вы хотите использовать [attributename~=attributevalue] вместо:

 Elements infoboxes = contentDiv.select("table[class~=infobox]");
// ...
  

или, что еще лучше, .classname селектор:

 Elements infoboxes = contentDiv.select("table.infobox");
// ...
  

Смотрите также:


Что касается вашего теста с другой записью в Википедии, я не могу воспроизвести это. Но я могу сказать, что эта страница содержит другую <table class="infobox"> , которая должна быть той, которую вы на самом деле извлекаете.

Комментарии:

1. Я, должно быть, идиот: все это время я обращал внимание на фундаментальную разницу между tag.["class=classname"] ( точным совпадением) обозначением и tag.classname (неточная) нотация, но я поменял их местами, а затем потратил слишком много времени на выяснение того, что происходит. 25.