如何使用Mechanize中的已解析值忽略循环中的nil值?

时间:2015-05-08 16:06:45

标签: ruby null mechanize-ruby

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

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

如果我使用Rails,我已经读过并看过解决方案,但对于Ruby,我只看到rejectcompact作为忽略nil值的可能解决方案。我在循环结束时添加了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!

这只是这样一个文本中的网址列表:

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

这将在控制台中输出,例如:

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

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

2 个答案:

答案 0 :(得分:0)

这是一种方法:

编辑(添加要求不跳过任何网址):

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

答案 1 :(得分:0)

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

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,但逻辑会很混乱,puts内的map很少使用。 (可能不应该使用更可能,但这是一个不同的主题。)