Nokogiri Timeout ::抓取自己的网站时出错

时间:2013-10-04 20:18:13

标签: ruby-on-rails ruby ruby-on-rails-3 nokogiri

Nokogiri在控制台中对我很好,但如果我把它放在任何地方......模型,视图或控制器,它会超时。

我想用2种方式之一...

控制器

def show
  @design = Design.find(params[:id])
  doc = Nokogiri::HTML(open(design_url(@design)))
  images = doc.css('.well img') ? doc.css('.well img').map{ |i| i['src'] } : []
end

...或

模型

def first_image
  doc = Nokogiri::HTML(open("http://localhost:3000/blog/#{self.id}"))
  image = doc.css('.well img')[0] ? doc.css('.well img')[0]['src'] : nil
  self.update_attribute(:photo_url, image)
end

两者都会导致超时,但它们在控制台中完美运行。

3 个答案:

答案 0 :(得分:2)

当您从控制台运行Nokogiri代码时,您将在localhost:3000引用您的开发服务器。因此,有两个实例正在运行:一个进行呼叫(您的控制台)和一个应答呼叫(您的服务器)

当您从应用程序中运行它时,您正在引用应用程序本身,这会导致无限循环,因为没有可用资源来响应您的呼叫(该资源是进行呼叫的资源!)。因此,您需要使用Unicorn(或者只是另一个端口上的另一个localhost实例)运行多个实例,并且您至少需要其中一个实例可以自由地回答Nokogiri请求。

如果您计划在生产中运行此功能,请知道此设置将需要可用资源来回答Nokogiri请求,因此您实际上每次调用都会占用2个实例。因此,如果您有4个实例并且所有4个实例同时进行调用,则整个应用程序都会被搞砸。你可能会遇到非常严重的恶化,一次只有1或2个电话......

答案 1 :(得分:1)

我不确定超时的默认值是什么。 但您可以指定一些超时值,如下所示。

require 'net/http'

http = Net::HTTP.new('localhost')
http.open_timeout = 100
http.read_timeout = 100
Nokogiri.parse(http.get("/blog/#{self.id}").body)

最后,您可以找到问题,因为您可以控制超时值。

答案 2 :(得分:-1)

所以,根据泰勒的建议,我挖掘了我正在做的事情。由于ckeditor与图像的断开,由于载波和S3,我无法直接从上传器获取任何信息(至少对我而言似乎是这样)。

相反,我坚持使用nokogiri,而且它的工作非常好。我意识到我实际使用open()命令做了什么,这完全没必要。 Nokogiri解析HTML。我可以以@design.content的形式给它HTML格式!呃,就我而言。

所以,这就是我正在抓取自己的网站,以获取与博客条目相关的图像:

<强> designs_controller.rb

def create
  params[:design][:photo_url] = Nokogiri::HTML(params[:design][:content]).css('img').map{ |i| i['src']}[0]
  @design = Design.new(params[:design])
  if @design.save
    flash[:success] = "Design created"
    redirect_to designs_url
  else
    render 'designs/new'
  end
end

def show
  @design = Design.find(params[:id])
  @categories = @design.categories
  @tags = @categories.map {|c| c.name}
  @related = Design.joins(:categories).where('categories.name' => @tags).reject {|d| d.id == @design.id}.uniq
  set_meta_tags og: {
    title: @design.name,
    type: 'article',
    url: design_url(@design),
    image: Nokogiri::HTML(@design.content).css('img').map{ |i| i['src']},
    article: {
      published_time: @design.published_at.to_datetime,
      modified_time: @design.updated_at.to_datetime,
      author: 'Alphabetic Design',
      section: 'Designs',
      tag: @tags
    }
  }
end

“更新”操作与“创建”操作具有相同的Nokogiri代码。

现在看起来很明显,我正在看着它,哈哈。我对此的研究时间比我想承认的还要长......