2016-09-12 2 views
0

Я пытаюсь получить текст Last sold date из этого HTML:Как я могу получить текст первого элемента с помощью Nokogiri?

<td class="browse-cell-date"> 

    <span title="Last sold date"> 
     May 2002 
    </span> 

    <button class="btn btn-previous-sales js-btn-previous-sales"> 
     Previous sales (1) <i class="icon icon-down-open-1"/> 
    </button> 

    <div class="previous-sales-panel is-hidden"> 
     <span style="display: block;"> 
      Aug 1997 
      <span class="fright">£60,000</span> 
     </span> 
    </div> 

</td> 

Я попытался:

date = val.search(".//td[@class='browse-cell-date']").children[1] 

Он дал мне срок я хотел, но после добавления .text к ней, ничего не вернулся ,

+0

Вы пробовали '.val()'? – davidhu2000

+0

@ davidhu2000, просто использовал 'val' и получил err' NoMethodError (неопределенный метод 'val 'для nil: NilClass):' – Raaz

ответ

1

Я хотел бы начать с:

require 'nokogiri' 

doc = Nokogiri::HTML(<<EOT) 
    <td class="browse-cell-date"> 

     <span title="Last sold date"> 
      May 2002 
     </span> 

     <button class="btn btn-previous-sales js-btn-previous-sales"> 
      Previous sales (1) <i class="icon icon-down-open-1"/> 
     </button> 

     <div class="previous-sales-panel is-hidden"> 
      <span style="display: block;"> 
       Aug 1997 
       <span class="fright">£60,000</span> 
      </span> 
     </div> 

    </td> 
EOT 

sold_date = doc.at('span[title="Last sold date"]') # => #<Nokogiri::XML::Element:0x3ffc7e84c35c name="span" attributes=[#<Nokogiri::XML::Attr:0x3ffc7e84c2f8 name="title" value="Last sold date">] children=[#<Nokogiri::XML::Text:0x3ffc7e82bc10 "\n   May 2002 \n  ">]> 
sold_date.text # => "\n   May 2002 \n  " 
sold_date.text.strip # => "May 2002" 

Так

doc.at('span[title="Last sold date"]').text.strip # => "May 2002" 

будет делать это.

at как search('some selector').first поэтому используйте это для удобства. Оба at и search достаточно умны, чтобы выяснить, является ли селектор CSS или XPath большую часть времени, поэтому я их использую. Если Nokogiri обманут, я вернусь к использованию одного из вариантов или *_xpath.

В качестве альтернативы вы можете использовать:

doc.at('td.browse-cell-date span').text.strip # => "May 2002" 
doc.at('td.browse-cell-date > span').text.strip # => "May 2002" 

Примечание: Использование text с любым из методов 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" 

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

99.99% времени, вы хотите использовать следующую map(&:text) для извлечения текста из NodeSet:

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

Но в вашем использовании, просто используйте at, которая возвращает узел, а затем text будет делать то, что вы ожидаете ,

+0

См. Http://stackoverflow.com/q/43594656/128421 –

0

Предполагая, что ваш td имеет класс 'browse-cell-date', и вы пытаетесь получить текст из первого диапазона непосредственно рядом с ним, вы можете сделать следующее, если хотите использовать формат xpath:

require 'nokogiri' 
page = Nokogiri::HTML(open('file.html')) 
page.xpath('//html/body/td/span[1]').text.strip 
# => "May 2002" 
# or also 
page.xpath('//html/body/td/span').text.strip 
# => "May 2002" 

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

И если вы хотите попробовать использовать CSS селекторы, вы можете сделать следующее:

require 'nokogiri' 
page = Nokogiri::HTML(open('file.html')) 
page.css('td > span').text.strip 
# => "May 2002" 

Использование CSS короче Xpath, но здесь вы можете сделать, как вы, если то, что дело в том, чтобы добраться до «Май 2002 года».

+0

Мне нужно было сделать что-то подобное, чтобы получить текст первого элемента 'val.search (".//td[@class='browse-cell-date']").search(".//span[@title='Last sold date ']"). text.strip' – Raaz

+1

И 'страница. xpath ('// html/body/td/span [1]'). text.strip' не сработал для вас? Я думаю, что это более короткая версия, чтобы получить текст внутри пролета, так или иначе, рад, что вы могли решите свою проблему –

+0

Будьте осторожны, указав полный путь к узлу. Если HTML изменится, код сломается. Вместо этого найдите путевые точки и используйте их для навигации. –

-2

Попробуйте

page.search(".//td").children[1].attr("title") 
+0

OP не хочет содержимого параметра 'title', а не того, что находится в первом' '. –

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