#html #html-parsing #jsoup
#HTML #html-синтаксический анализ #jsoup
Вопрос:
Извлечение значения href из следующего примера HTML-кода выполняется просто, если я перебираю все и прерываю работу сразу после первого:
<li class="parts partname parts_first">
<div id="dpdn10" uri="/public/page/part1" class="partype partstate">
<div class="ptctainer">
<div class="ptitle">
<p class="ptypead">
<span class="rtext"><a href="http://www.example.com/page/ptname.html?dv=rfirst" class="mnLabel">First</a></span>
<span class="ndx">
<a href="#" dndx="dpdn10" class="xpnd _t" style="opacity:1">Details: </a>
</span>
</p>
</div>
</div>
<div id="dpdn10_content" class="xpns">
<div class="ptctainer">
<div class="ptitle">
<p class="ptypead">
<span class="rtext"><a href="http://www.example.com/page/ptname.html?dv=rfirst" class="mnLabel">First</a></span>
<span class="ndx"><a href="#" class="xpnd">Details: </a></span>
</p>
</div>
</div>
</div>
</div>
</li>
Я, конечно, могу это сделать, когда могу предположить, что значение href одинаково для обоих экземпляров, как в примере выше.
Однако этот подход терпит неудачу, если они не идентичны, и я хочу извлечь конкретный элемент (либо первый, либо второй).
Что подводит меня к поиску механизма в Jsoup, который допускает «вложенный выбор»: до сих пор я был знаком с одноуровневым выбором, как в:
Elements links = doc.select("a[href]"); // a with href
Elements pngs = doc.select("img[src$=.png]"); // img with src ending .png
Element masthead = doc.select("div.masthead").first(); // div with class=masthead
Но я не могу найти документацию или пример для многоуровневого выбора, например
Element link= doc.select("div.xpns.div.ptctainer.div.ptitle.p.ptypead.span.rtext");
Приведенное выше приведено для иллюстрации, а не для реального синтаксиса, конечно. Я не знаю, возможно ли что-то подобное (пока) в Jsoup.
Существует ли такой «вложенный выбор» в Jsoup?
Ответ №1:
Селекторы jsoup работают точно так же, как CSS. Смотрите документ Selector для получения полной поддержки.
Вы можете выполнять дочерние выборки следующим образом:
Element link = doc.select("div.xpns div.ptctainer div.ptitle p.ptypead span.rtext").first();
Если имя тега не важно для выбора, и вам нужно использовать только имя класса:
Element link = doc.select(".xpns .ptctainer .ptitle .ptypead .rtext").first();
Эти запросы очень эффективны.
Ответ №2:
Разве вы не можете просто «связать» функции выбора? Нравится:
Element link = doc.select("div.xpns").select("div.ptctainer").select("div.ptitle").select("p.ptypead").select("span.rtext");
Комментарии:
1. Конечно, я могу, но «цепная» форма подразумевает менее оптимизированный обход / синтаксический анализ. Я надеялся, что, возможно, Jsoup оптимизирует такой сценарий. Спасибо и 1.
2. Синтаксический анализ всегда выполняется медленно. В идеале вы бы пропустили все это вместе.
3. Я надеялся, что Jsoup будет иметь многоуровневый механизм, аналогичный тому, который уже есть у дочернего элемента-предка. Но, похоже, это пока недоступно.