你所需输出是无稽之谈:
['Raw name 1', 2,094, 0,017, 0,098, 0,113, 0,452]
# ~> -:1: Invalid octal digit
# ~> ['Raw name 1', 2,094, 0,017, 0,098, 0,113, 0,452]
我假设你想要引用的数字。
剥离,保持代码的工作,并减少HTML更易于管理的例子,东西之后再运行它:
require 'nokogiri'
html = <<EOT
<table class="open">
<tr>
<th>Table name</th>
<th>Column name 1</th>
<th>Column name 2</th>
</tr>
<tr>
<th>Raw name 1</th>
<td>2,094</td>
<td>0,017</td>
</tr>
<tr>
<th>Raw name 5</th>
<td>2,094</td>
<td>0,017</td>
</tr>
</table>
EOT
doc = Nokogiri::HTML(html)
tables = doc.css('table.open')
tables_data = []
tables.each do |table|
title = table.css('tr[1] > th').text # !> assigned but unused variable - title
cell_data = table.css('tr > td').text
raw_name = table.css('tr > th').text
tables_data << [cell_data, raw_name]
end
导致:
tables_data
# => [["2,0940,0172,0940,017",
# "Table nameColumn name 1Column name 2Raw name 1Raw name 5"]]
的第一件事注意你是不是在使用title
,虽然你指定它。例如,当您清理代码时可能发生这种情况。
css
,如search
和xpath
,返回一个NodeSet,类似于一个节点数组。当您在使用节点集或text
它inner_text
返回连接成一个字符串中每个节点的文本:
获取包含的所有Node对象的内部文本。
这是它的行为:
require 'nokogiri'
doc = Nokogiri::HTML('<html><body><p>foo</p><p>bar</p></body></html>')
doc.css('p').text # => "foobar"
相反,你应该遍历找到的每个节点,并单独提取其文本。这部分内容的很多倍SO:
doc.css('p').map{ |node| node.text } # => ["foo", "bar"]
这可以简化为:
doc.css('p').map(&:text) # => ["foo", "bar"]
见 “How to avoid joining all text from Nodes when scraping” 也。
文档说这个约content
,text
和inner_text
一个节点时:
返回此节点的内容。
相反,你需要的单个节点的文本之后去:
require 'nokogiri'
html = <<EOT
<table class="open">
<tr>
<th>Table name</th>
<th>Column name 1</th>
<th>Column name 2</th>
<th>Column name 3</th>
<th>Column name 4</th>
<th>Column name 5</th>
</tr>
<tr>
<th>Raw name 1</th>
<td>2,094</td>
<td>0,017</td>
<td>0,098</td>
<td>0,113</td>
<td>0,452</td>
</tr>
<tr>
<th>Raw name 5</th>
<td>2,094</td>
<td>0,017</td>
<td>0,098</td>
<td>0,113</td>
<td>0,452</td>
</tr>
</table>
EOT
tables_data = []
doc = Nokogiri::HTML(html)
doc.css('table.open').each do |table|
# find all rows in the current table, then iterate over the second all the way to the final one...
table.css('tr')[1..-1].each do |tr|
# collect the cell data and raw names from the remaining rows' cells...
raw_name = tr.at('th').text
cell_data = tr.css('td').map(&:text)
# aggregate it...
tables_data += [raw_name, cell_data]
end
end
现在导致:
tables_data
# => ["Raw name 1",
# ["2,094", "0,017", "0,098", "0,113", "0,452"],
# "Raw name 5",
# ["2,094", "0,017", "0,098", "0,113", "0,452"]]
你能弄清楚如何要挟引用数为小数接受到Ruby,或者你想要的操作内部数组。
请降低你的代码需要说明问题的最低限度。在问题本身*中提供一个最小的HTML *示例,它也演示了这个问题。不要要求我们去页面提取HTML或建立必要的周边代码来测试你的。阅读“[问]”,“[mcve]”和http://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/ –
@锡人感谢。我更新了我的代码。相信现在看起来好多了? – verrom
一般信息为一般人寻找这个主题:http://ruby.bastardsbook.com/chapters/web-crawling/ – benjamin