删除/忽略不需要的文本不是Nokogiri问题,它是字符串处理问题:
require 'nokogiri'
doc = Nokogiri::HTML(<
li class="object-props-item price"
CHF 14'900.-
61'000 kmEOT
str = doc.at('strong').text # => "CHF 14'900.-"
此时str包含节点的文本。
一个简单的正则表达式将被提取,这是获取数据的直接方式:
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('
61'000 km')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 `'
相反它应该是:
doc.css('.milage').text # => "61'000 km"
但这并非全是错误的。有一个微妙的问题等着你以后咬你。
css或search返回一个NodeSet,而at或at_css返回一个元素:
doc.css('.milage').class # => Nokogiri::XML::NodeSet
doc.at('.milage').class # => Nokogiri::XML::Element
以下是text传递包含多个匹配节点的NodeSet时会发生什么:
doc = Nokogiri::HTML('
foo
bar
')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"]
最后,请注意您的HTML示例无效:
doc = Nokogiri::HTML(<
li class="object-props-item price"
CHF 14'900.-
61'000 km')EOT
puts doc.to_html
# >>
# >>
# >>
li class="object-props-item price"
# >> CHF 14'900.-
# >>
# >>
61'000 km')# >>
以下是发生的事情:
doc = Nokogiri::HTML(<
li class="object-props-item price"
CHF 14'900.-
61'000 km')EOT
doc.at('.price') # => nil
Nokogiri必须做一个修复才能理解第一行,所以它将它包含在
中。通过这样做,.price类不再存在,因此您的代码将再次失败。
修复标记会产生正确的响应:
doc = Nokogiri::HTML(<
CHF 14'900.-
61'000 km')EOT
doc.at('.price').to_html # => "
\n CHF 14'900.-\n"这就是为什么确保您的输入有效非常重要。如果没有它,试图复制你的问题是很困难的。