2016-09-12 41 views
0

我想從這個HTML爲Last sold date文本:如何使用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'並得到了一個錯誤'NoMethodError(未定義的方法val'爲零: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所以用它來方便。 atsearch都足夠聰明,可以在大多數情況下確定選擇器是CSS還是XPath,因此我使用這些選擇器。如果Nokogiri被愚弄,我會恢復使用*_css*_xpath變體之一。

或者你可以使用:

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

注意:使用text與任何searchxpathcss方法是不是一個好主意。這些方法返回一個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)來提取節點集文字:

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年5月」。

+0

我必須這樣做才能得到第一個元素的文本 'val.search (「.//td[@class='browse-cell-date']").search(".//span[@title='Last sold date']」)。text.strip' – Raaz

+1

And'page。 xpath('// html/body/td/span [1]')。text.strip'對你不起作用,我認爲這是一個縮短版本的文本,不管怎樣,很高興你能夠解決您的問題 –

+0

請小心指定節點的完整路徑。如果HTML更改,代碼將會中斷。相反,找到方向點並使用它們進行導航。 –

-2

試試這個

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

OP不需要'title'參數的內容,而是第一個''中的內容。 –

相關問題