Вы пытаетесь найти текстовый узел, который следует <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».
Удивительный! Большое спасибо! Почему вы используете вместо .css или .xpath? :) – AaronDT
См. Дополнительную информацию. –
Рад, что это помогло. Идея о переполнении стека заключается в том, что мы пишем он-лайн справочник, поэтому хорошие вопросы и ответы помогают остальному миру программирования. Это не только помогает вам, но и помогает следующему человеку найти решение аналогичной проблемы. Продолжайте задавать хорошие вопросы, затем начинайте отвечать на них и учите их тому, что вы узнали. –