【问题标题】:Rails 5 model with Nokogri gem return nil带有 Nokogri gem 的 Rails 5 模型返回 nil
【发布时间】:2017-03-15 14:19:36
【问题描述】:

我在 Rails 5 中的应用程序有问题。我创建了 scrape.rb 类 通过 Nokogiri gem 抓取 HTML 并可以将这些数据保存在另一个模型中,但是当我在 rails 控制台中创建新对象时,它返回 nil 并且不废弃任何值:

2.3.0 :018 > s = Scrape.new
 => #<Scrape:0x007fba68b79e98>
2.3.0 :019 > s.scrape_new_movie
 => nil
2.3.0 :020 >

这里是scrape.rb模型

 class Scrape
  attr_accessor :title, :vote, :image_url, :description,

  def scrape_new_movie
    begin
      doc = Nokogiri::HTML(open("https://zalukaj.com/zalukaj-film/26280/barbie_w_wiecie_gier_barbie_video_game_hero_2017_.html").read, nil, 'utf-8')
      doc.css('script').remove
      self.title = doc.css('#pw_title.about_movie_title').text
      v = doc.css('#success_vote').text
      self.vote = v.slice(2...5)
      self.image_url = doc.css('.about_movie img').attr('src').text
      self.description = doc.css('#pw_description.e_s3k').text
      return true
      rescue Exception => e
      self.failure = "Something went wrong with the scrape"
    end
  end

  def save_movie
    movie = Movie.new(
      title: self.title,
      vote: self.vote,
      image_url: self.image_url,
      description: self.description
    )
    movie.save
  end
end

【问题讨论】:

  • 运行s.scrape_new_movie后,s.failure返回什么?
  • 尝试删除begin/rescue/end,看看会发生什么错误。
  • 当我删除它时,值仍然为零。我如何检查s.failure 返回的内容?
  • 在您运行s.scrape_new_movie的同一个控制台实例中,输入s.failure
  • 好的,所以当我输入 s.failure 时,它现在返回 NoMethodError: undefined method failure' for #<0x007f92e69f37f8>

标签: ruby web-scraping nokogiri ruby-on-rails-5 activemodel


【解决方案1】:

它返回nil 的原因是因为您以逗号结尾attr_accessor。变量 failure 也未定义,所以我假设您也需要一个 attr_accessor。

你应该改变

  attr_accessor :title, :vote, :image_url, :description,

  attr_accessor :title, :vote, :image_url, :description, :failure

【讨论】:

  • 是的,它现在可以工作了!非常感谢您的提示。
【解决方案2】:

替换方法:

  def scrape_new_movie
    begin
      doc = Nokogiri::HTML(open("https://zalukaj.com/zalukaj-film/26280/barbie_w_wiecie_gier_barbie_video_game_hero_2017_.html").read, nil, 'utf-8')
      doc.css('script').remove
      self.title = doc.css('#pw_title.about_movie_title').text
      v = doc.css('#success_vote').text
      self.vote = v.slice(2...5)
      self.image_url = doc.css('.about_movie img').attr('src').text
      self.description = doc.css('#pw_description.e_s3k').text
      return true
      rescue Exception => e
      self.failure = "Something went wrong with the scrape"
    end
  end

  def scrape_new_movie
    doc = Nokogiri::HTML(open("https://zalukaj.com/zalukaj-film/26280/barbie_w_wiecie_gier_barbie_video_game_hero_2017_.html").read, nil, 'utf-8')
    doc.css('script').remove
    self.title = doc.css('#pw_title.about_movie_title').text
    v = doc.css('#success_vote').text
    self.vote = v.slice(2...5)
    self.image_url = doc.css('.about_movie img').attr('src').text
    self.description = doc.css('#pw_description.e_s3k').text
    return true
  end

然后发生的任何错误都会冒泡并以允许您调试问题所在的方式显示。

这是一个很好的例子,说明为什么你永远不应该这样做rescue Exception,因为这总是让调试问题变得更加困难。见:Why is it a bad style to `rescue Exception => e` in Ruby?

【讨论】:

  • 好的,但是当我替换像你这样的方法时,它仍然为零,我不知道如何调试它。
  • 代码中还有其他rescue子句吗?
【解决方案3】:

根据您的设置方式,无需调用类的字面名称。只需添加自我。到方法,不要调用新的。如果要调试此脚本,此脚本中也有很多错误,我还会引发异常消息。您还应该将 self.title = 更改为 @title = 或者如果您想保留 self.title 您需要添加从 self 继承的类并将 attr_accessor 放在该类中。

class Scrape
  class << self
    attr_accessor :title, :vote, :image_url, :description, failure
  end 

  def self.scrape_new_movie
    begin
      doc = Nokogiri::HTML(open("https://zalukaj.com/zalukaj-film/26280/barbie_w_wiecie_gier_barbie_video_game_hero_2017_.html").read, nil, 'utf-8')
      doc.css('script').remove
      self.title = doc.css('#pw_title.about_movie_title').text
      v = doc.css('#success_vote').text
      self.vote = v.slice(2...5)
      self.image_url = doc.css('.about_movie img').attr('src').text
      self.description = doc.css('#pw_description.e_s3k').text
      return true
      rescue Exception => e
        raise e 
      end
    end

    def self.save_movie
      movie = Movie.new(
        title: self.title,
        vote: self.vote,
        image_url: self.image_url,
        description: self.description
      )
      movie.save
    end
 end      
 Scrape.scrape_new_movie

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多