2016-02-24 2 views
1

Я столкнулся с проблемой с моим запросом XPath. Мне нужно разобрать div, который делится на неизвестное количество «разделов». Каждый из них разделяется h5 с именем раздела. Список возможных названий разделов известен, и каждый из них может появляться только один раз. Кроме того, каждый раздел может содержать некоторые теги br. Итак, допустим, я хочу извлечь текст в разделе «SecondHeader».XPath - извлечение текста между двумя узлами

HTML

<div class="some-class"> 
<h5>FirstHeader</h5> 
    text1 
<h5>SecondHeader</h5> 
    text2a<br> 
    text2b 
<h5>ThirdHeader</h5> 
    text3a<br> 
    text3b<br> 
    text3c<br> 
<h5>FourthHeader</h5> 
    text4 
</div> 

Ожидаемый результат (для SecondSection)

['text2a', 'text2b'] 

Запрос # 1

//text()[following-sibling::h5/text()='ThirdHeader'] 

Результат # 1

['text1', 'text2a', 'text2b'] 

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

запрос # 2

//text()[following-sibling::h5/text()='ThirdHeader' and preceding-sibling::h5/text()='SecondHeader'] 

Результат # 2

['text2a', 'text2b'] 

Поддавшись результаты соответствуют ожиданиям. Однако это нельзя использовать - я не знаю, будет ли SecondHeader/ThirdHeader существовать на анализируемой странице или нет. В запросе необходимо использовать только один заголовок раздела.

запрос # 3

//text()[following-sibling::h5/text()='ThirdHeader' and not[preceding-sibling::h5/text()='ThirdHeader']] 

Результат # 3

[] 

Не могли бы вы сказать мне, что я делаю неправильно? Я тестировал его в Google Chrome.

ответ

1

Вы должны иметь возможность просто проверить первый предшествующий Sibling h5 ...

//text()[preceding-sibling::h5[1][normalize-space()='SecondHeader']] 
2

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

lxml Пример использования (в Python)

>>> import lxml.html 
>>> s = ''' 
... <div class="some-class"> 
... <h5>FirstHeader</h5> 
... text1 
... <h5>SecondHeader</h5> 
... text2a<br> 
... text2b 
... <h5>ThirdHeader</h5> 
... text3a<br> 
... text3b<br> 
... text3c<br> 
... <h5>FourthHeader</h5> 
... text4 
... </div>''' 
>>> doc = lxml.html.fromstring(s) 
>>> doc.xpath("//text()[count(preceding-sibling::h5)=$count]", count=1) 
['\n text1\n '] 
>>> doc.xpath("//text()[count(preceding-sibling::h5)=$count]", count=2) 
['\n text2a', '\n text2b\n '] 
>>> doc.xpath("//text()[count(preceding-sibling::h5)=$count]", count=3) 
['\n text3a', '\n text3b', '\n text3c', '\n '] 
>>> doc.xpath("//text()[count(preceding-sibling::h5)=$count]", count=4) 
['\n text4\n'] 
>>> 
Смежные вопросы