刪除/忽略不需要的文本是不是一個引入nokogiri問題,這是一個字符串處理的問題:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
li class="object-props-item price"
<strong>CHF 14'900.-</strong>
<li class="object-props-item milage">61'000 km</li>
EOT
str = doc.at('strong').text # => "CHF 14'900.-"
此時str
包含<strong>
節點的文本。
一個簡單的正則表達式將提取,這是爲了獲取數據的直接方式:
str[/[\d']+/] # => "14'900"
sub
可以用來除去'CHF '
子:
str.sub('CHF ', '') # => "14'900.-"
delete
可用於除去字符C
,H
,F
和
:
str.delete('CHF ') # => "14'900.-"
tr
可以用來去除一切不是0
.. 9
,'
,.
或-
:
str.tr("^0-9'.-", '') # => "14'900.-"
修改上面的一個,如果你不想'
,.
或-
做。
爲什麼的里程不顯示
的數據,因爲你的CSS選擇器和實際class
參數之間的不匹配:
require 'nokogiri'
doc = Nokogiri::HTML('<li class="object-props-item milage">61'000 km</li>')
doc.at('.mileage').text # =>
# ~> NoMethodError
# ~> undefined method `text' for nil:NilClass
# ~>
# ~> /var/folders/yb/whn8dwns6rl92jswry5cz87dsgk2n1/T/seeing_is_believing_temp_dir20160428-96035-1dajnql/program.rb:5:in `<main>'
相反,它應該是:
doc.css('.milage').text # => "61'000 km"
但這並不全是錯的。有一個微妙的問題等待你咬你。
css
或search
返回一個節點集而at
或at_css
返回一個元素:
doc.css('.milage').class # => Nokogiri::XML::NodeSet
doc.at('.milage').class # => Nokogiri::XML::Element
下面是當text
傳遞包含多個匹配的節點一個節點集會發生什麼:
doc = Nokogiri::HTML('<p>foo</p><p>bar</p>')
doc.search('p').class # => Nokogiri::XML::NodeSet
doc.search('p').text # => "foobar"
doc.at('p').class # => Nokogiri::XML::Element
doc.at('p').text # => "foo"
當使用text
使用NodeSet,它將所有節點的文本連接成單個字符串。這可能會使文本從一個節點與另一個節點分離變得非常困難。相反,使用at
或其中一個at_*
等價物可從單個節點獲取文本。如果你想單獨提取每個節點的文本,並得到一個陣列中使用:
doc.search('p').map(&:text) # => ["foo", "bar"]
見「How to avoid joining all text from Nodes when scraping」也。
最後,注意你的HTML示例是無效的:
doc = Nokogiri::HTML(<<EOT)
li class="object-props-item price"
<strong>CHF 14'900.-</strong>
<li class="object-props-item milage">61'000 km</li>')
EOT
puts doc.to_html
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html><body>
# >> <p>li class="object-props-item price"
# >> <strong>CHF 14'900.-</strong>
# >> </p>
# >> <li class="object-props-item milage">61'000 km</li>')
# >> </body></html>
這裏發生了什麼:
doc = Nokogiri::HTML(<<EOT)
li class="object-props-item price"
<strong>CHF 14'900.-</strong>
<li class="object-props-item milage">61'000 km</li>')
EOT
doc.at('.price') # => nil
引入nokogiri已經做了修復行動,使第一線的感覺,所以它包裝在<p>
。通過這樣做,.price
類不再存在,因此您的代碼將再次失敗。
固定的標籤結果的正確響應:
doc = Nokogiri::HTML(<<EOT)
<li class="object-props-item price">
<strong>CHF 14'900.-</strong>
</li>
<li class="object-props-item milage">61'000 km</li>')
EOT
doc.at('.price').to_html # => "<li class=\"object-props-item price\">\n<strong>CHF 14'900.-</strong>\n</li>"
這就是爲什麼它,以確保您的輸入有效真的很重要。沒有它,試圖複製你的問題是困難的。
我不認爲這是你的問題的原因,但你打開文件以二進制模式寫入('wb')。 CSV是一個文本表示,所以我很確定你應該以文本模式('w')打開它。 –
當詢問您的代碼有問題時,我們需要看到您嘗試解決問題。在您的代碼中,您不會顯示您試圖刪除CHF和KM數據的位置;請補充一點。沒有它,看起來你問我們如何編寫你的代碼,這不是它的目的。此外,你的「結果」不應該是一個圖像的鏈接。相反,請在問題本身中提供這些信息。 「[mcve]」描述我們需要的東西。要刪除這些信息,使用檢索到的文本上的'delete'或'sub'或更好的方法,使用'tr'來刪除你不想要的東西,或者寫一個正則表達式來只提取你想要的東西。 –
此外,您的輸入HTML無效。爲了解釋爲什麼這很重要,請參閱我的答案。 –