如何忽略循环中的 nil 值以及来自 Mechanize 的解析值?



在我的文本文件中有一个URL列表。使用 Mechanize,我正在使用该列表来解析标题和元描述。但是,其中一些 URL 页面没有元描述,这会因 nil 错误而停止我的脚本:

undefined method `[]' for nil:NilClass (NoMethodError)

如果我使用 Rails,我已经阅读并看到了解决方案,但对于 Ruby,我只看到了rejectcompact作为忽略零值的可能解决方案。我在循环结束时添加了compact,但这似乎没有任何作用。

require 'rubygems'
require 'mechanize'
File.readlines('parsethis.txt').each do |line|
page = Mechanize.new.get(line)
title = page.title
metadesc = page.at("head meta[name='description']")[:content]
puts "%s, %s, %s" % [line.chomp, title, metadesc] 
end.compact!

它只是文本中的 url 列表,如下所示:

http://www.a.com
http://www.b.com

这是将在控制台中输出的内容,例如:

http://www.a.com, Title, This is a description.

如果在 URL 列表中该特定页面上没有描述或标题,则会引发 nil 错误。我不希望它跳过任何网址,我希望它遍历整个列表。

这里有一种方法可以做到这一点:

编辑(用于不跳过任何网址的附加要求):

metadesc = page.at("head meta[name='description']")
puts "%s, %s, %s" % [line.chomp, title, metadesc ? metadesc[:content] : "N/A"]

这是未经测试的,但我会做这样的事情:

require 'open-uri'
require 'nokogiri'
page_info = {}
File.foreach('parsethis.txt') { |url|
page = Nokogiri::HTML(open(url))
title = page.title
meta_desc = page.at("head meta[name='description']")
meta_desc_content = meta_desc ? meta_desc[:content] : nil
page_info[url] = {:title => title, :meta_desc => meta_desc_content} 
}
page_info.each do |url, info|
puts [
url,
info[:title],
info[:meta_desc]
].join(', ')
end
  • File.foreach以迭代方式读取文件,分别返回每一行。
  • 如果页面没有标题,page.title可以返回 nil;标题在页面中可选的。
  • 我将访问元描述分为两个步骤。元标记在 HTML 中是可选的,因此它们可能不存在,此时将返回 nil。尝试访问content=参数将导致异常。我想这就是你所看到的。

    相反,在我的代码中,如果找到元描述标签,则有条件地为meta_desc_content分配一个值,或者 nil。

该代码使用 URL 的键/值对及其关联的标题和元描述填充page_info哈希。我这样做是因为哈希的哈希,或者可能是哈希数组,对于各种辅助操作来说是一种非常方便的结构,例如将信息作为 JSON 返回或插入到数据库中。

作为第二步,代码遍历该哈希,检索每个键/值对。然后,它将值联接为字符串并打印它们。

你的代码中有很多东西要么是错误的,要么不是我的做法:

  • File.readlines('parsethis.txt').each返回一个数组,然后您必须迭代该数组。这是不可扩展的,也不是有效的。File.foreachFile.readlines(...).each快,所以养成使用它的习惯,除非您绝对确定自己知道为什么要使用readlines
  • 你可以使用 Mechanize 来完成 Nokogiri 和 OpenURI 可以更快地完成的事情。如果您正在使用表单并需要导航网站,Mechanize是一个很好的工具,但您没有这样做,因此您正在拖动不必要的额外代码权重。别这样;它会导致程序缓慢等。
  • page.at("head meta[name='description']")[:content]是等待中的例外。正如我上面所说,元描述不一定存在于页面中。如果没有,那么您正在尝试执行nil[:content]这肯定会引发异常。相反,你可以向下找到你想要的数据,这样你就可以在尝试获取其内容之前确保元描述存在。
  • 你不能像以前那样使用compactcompact!each块不返回数组,这是compactcompact!所需的类。你本可以使用map但逻辑会很混乱,map内部puts很少使用。(可能不应该使用的可能性更大,但这是一个不同的主题。

最新更新