2016-10-07 2 views
0

Я пытаюсь получить текст в пределах элемента <li>, который я идентифицирую с помощью элементов span, содержащих «Inhalt:».Как получить текст после тега внутри элемента li

Текст, который я хочу получить, составляет «0,75л».

Это HTML-код:

<li class="product--tax is-left"> 
    <span class="label--purchase-unit">Inhalt:</span> 
0,75 l #text I want to get 
</li> 

Если пытались это, однако это не похоже на работу:

doc.search("[text()*='Inhalt:']").parent.xpath('text()') 

ответ

1

Вы пытаетесь найти текстовый узел, который следует <span>. Это легко сделать, когда вы знаете, где <span> является:

require 'nokogiri' 

doc = Nokogiri::HTML(<<EOT) 

<li class="product--tax is-left"> 
    <span class="label--purchase-unit">Inhalt:</span> 
0,75 l 
</li> 
EOT 

Это различные способы, чтобы получить там:

doc.at('li span').next_sibling.text.strip # => "0,75 l" 
doc.at('li.product--tax span.label--purchase-unit').next_sibling.text.strip # => "0,75 l" 
doc.at('.label--purchase-unit').next_sibling.text.strip # => "0,75 l" 
doc.at('span.label--purchase-unit').next_sibling.text.strip # => "0,75 l" 

Переходим ...

doc.search("[text()*='Inhalt:']").parent.xpath('text()') 

это плохой способ попробуйте найти узел:

  • search возвращает NodeSet, который будет соответствовать всем узлам в документе. Хотя в этом конкретном использовании может быть только одно вхождение «Inhalt:», в другом документе, который имеет несколько экземпляров целевого слова, вы получите несколько обращений и получите результат мусора.
  • parent - это не метод NodeSet, чтобы он взорвался.
  • parent.xpath не является хорошим способом продолжения селектора. Вместо того, чтобы добиться этого в XPath вы должны использовать что-то вроде:

    [text()*='Inhalt:']/../text() 
    

    .. средства перехода к родителю текущего узла в XPath-жаргоне. Это не в моей голове, но выглядит правильно.


Почему вы используете в вместо .css или .xpath?

at эквивалентно search('some_selector').first, так что это сокращенная найти первое вхождение этого селектора. at и search - это общие методы, использующие XPath или CSS, и полагаться на некоторые эвристики, чтобы определить, является ли селектор XPath или строкой CSS. Они могут обмануть, но большую часть времени они полностью безопасны и более удобны, чем их xpath, css, at_xpath или at_css вариантов.

Если разметка может содержать несколько узлов, которые вы хотите идентифицировать, то необходимо соответствующим образом настроить использование at и search.

Есть точка смятения, которую мы видим, когда люди регулярно падают.at и варианты at_* возвращают узел, а search и его варианты xpath и css возвращают узел NodeSet. При попытке извлечь текст из поиска text сделает что-то неожиданное. Размышлять об этом:

require 'nokogiri' 

doc = Nokogiri::HTML(<<EOT) 
<html> 
    <body> 
    <p>foo</p> 
    <p>bar</p> 
    </body> 
</html> 
EOT 

doc.search('p').class # => Nokogiri::XML::NodeSet 
doc.search('p').text # => "foobar" 

doc.at('p').class # => Nokogiri::XML::Element 
doc.at('p').text # => "foo" 

doc.search('p').map(&:text) # => ["foo", "bar"] 

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

См. Также «How to avoid joining all text from Nodes when scraping».

+0

Удивительный! Большое спасибо! Почему вы используете вместо .css или .xpath? :) – AaronDT

+1

См. Дополнительную информацию. –

+0

Рад, что это помогло. Идея о переполнении стека заключается в том, что мы пишем он-лайн справочник, поэтому хорошие вопросы и ответы помогают остальному миру программирования. Это не только помогает вам, но и помогает следующему человеку найти решение аналогичной проблемы. Продолжайте задавать хорошие вопросы, затем начинайте отвечать на них и учите их тому, что вы узнали. –

Смежные вопросы