Html 为什么每个表行都有一条空白记录?
由于另一个SO问题/答案,我有以下代码:Html 为什么每个表行都有一条空白记录?,html,parsing,screen-scraping,nokogiri,Html,Parsing,Screen Scraping,Nokogiri,由于另一个SO问题/答案,我有以下代码: page = agent.page.search("table tbody tr").each do |row| time = row.css("td:nth-child(1)").text.strip source = row.css("td:nth-child(2)").text.strip destination = row.css("td:nth-child(3)").text.strip duration
page = agent.page.search("table tbody tr").each do |row|
time = row.css("td:nth-child(1)").text.strip
source = row.css("td:nth-child(2)").text.strip
destination = row.css("td:nth-child(3)").text.strip
duration = row.css("td:nth-child(4)").text.strip
Call.create!(:time => time, :source => source, :destination => destination, :duration => duration)
end
它工作得很好,当我运行rake任务时,它会将数据正确地放入Rails应用程序中的正确表行中,然而,由于某种原因,在成功地为一行创建记录之后,它也会创建一条空白记录
我想不出来。从代码的外观来看,它发出了create代码>每行中的命令
您可以在和处看到完整的rake任务
导致此代码的另一个问题是“.”根据注释:
我想你可能是对的,我已经在远程网页上查看了HTML,他们正在为每个分配了类的表行添加一个包装。我想知道是否有办法让脚本跳过空行
如果您看到的HTML结构如下:
<table>
<tbody>
<tr>
<tr>
<td>time</td>
<td>source</td>
<td>destination</td>
<td>duration</td>
</tr>
</tr>
</tbody>
</table>
<> P>获取空白行的原因是HTML格式错误。外面的
不应该在那里。修复很简单,而且可以使用正确的HTML
此外,内部css
访问并不十分正确,但其原因很微妙。我会说的
要解决第一个问题,我们将添加一个条件测试:
page = doc.search("table tbody tr").each do |row|
变成:
page = doc.search("table tbody tr").each do |row|
next if (!row.at('td'))
运行后,输出现在为:
{:time=>"time",
:source=>"source",
:destination=>"destination",
:duration=>"duration"}
这就是解决问题所需的全部内容,但代码中有一些内容是以艰难的方式进行的,这需要一些“splainin”,但首先是代码更改:
发件人:
改为:
time, source, destination, duration = row.search('td').map{ |td| td.text.strip }
运行该代码将输出您想要的:
{:time=>"time",
:source=>"source",
:destination=>"destination",
:duration=>"duration"}
所以事情还是很好
您的原始代码存在以下问题:
css
是search
的别名。Nokogiri为这两个节点返回一个节点集text
将从一个空节点集返回一个空字符串,您可以从查看外部
的行.css(“td:nth child(…)”).text.strip调用中得到该空字符串。所以,Nokogiri没有默默地做你想做的事情,因为它在语法上是正确的,在逻辑上也是正确的,因为你告诉它要做什么;它只是没有达到你的期望
使用at
,或其别名之一,如css\u at
,查找第一个匹配的访问器。因此,理论上,我们可以继续使用row.at(“td:nth child(1)”).text.strip
,为每个访问者分配多个任务,这会立即暴露出HTML有问题,因为text
会爆炸。但这还不够像禅宗
相反,我们可以使用map
对节点集中返回的单元格进行迭代,让它收集所需的单元格内容并将其剥离,然后对变量执行并行赋值:
time, source, destination, duration = row.search('td').map{ |td| td.text.strip }
同样,运行以下命令:
require 'nokogiri'
require 'pp'
html = '<table><tbody><tr><tr><td>time</td><td>source</td><td>destination</td><td>duration</td></tr></tr></tbody></table>'
doc = Nokogiri::HTML(html)
page = doc.search("table tbody tr").each do |row|
next if (!row.at('td'))
time, source, destination, duration = row.search('td').map{ |td| td.text.strip }
hash = {
:time => time,
:source => source,
:destination => destination,
:duration => duration
}
pp hash
end
将其改装到您的代码中,您将获得:
page = agent.page.search("table tbody tr").each do |row|
next if (!row.at('td'))
time, source, destination, duration = row.search('td').map{ |td| td.text.strip }
Call.create!(:time => time, :source => source, :destination => destination, :duration => duration)
end
您可能不需要页面=
我怀疑HTML中有某种东西导致了中间循环,但没有填充值,例如没有内容的附加行。我认为您可能是对的,我查看了远程网页上的HTML,他们正在为分配了类的每个表行添加一个包装。我想知道是否有办法让脚本跳过空行?添加一个HTML示例,其中包含两行和单元格。那我们就可以解决问题了。没有这些,我们只是猜测。确保。看看下面我的答案。哇,写得好-谢谢!我现在要好好读一遍,试试你的建议。
time, source, destination, duration = row.search('td').map{ |td| td.text.strip }
require 'nokogiri'
require 'pp'
html = '<table><tbody><tr><tr><td>time</td><td>source</td><td>destination</td><td>duration</td></tr></tr></tbody></table>'
doc = Nokogiri::HTML(html)
page = doc.search("table tbody tr").each do |row|
next if (!row.at('td'))
time, source, destination, duration = row.search('td').map{ |td| td.text.strip }
hash = {
:time => time,
:source => source,
:destination => destination,
:duration => duration
}
pp hash
end
{:time=>"time",
:source=>"source",
:destination=>"destination",
:duration=>"duration"}
page = agent.page.search("table tbody tr").each do |row|
next if (!row.at('td'))
time, source, destination, duration = row.search('td').map{ |td| td.text.strip }
Call.create!(:time => time, :source => source, :destination => destination, :duration => duration)
end