1

我正在寻找一种能够实现的解决方案:

  1. 重复执行抓取任务(nokogiri)
  2. 通过http://www.myapp.com/interval更改时间间隔(示例)

完成这项工作的最佳解决方案/方法是什么?

我知道的选项

  • 自定义耙子任务
  • 鲁弗斯调度器

现在的情况

./config/initializers/task_scheduler.rb我有:

require 'nokogiri'
require 'open-uri'
require 'rufus-scheduler'
require 'rake'

scheduler = Rufus::Scheduler.new

scheduler.every "1h" do
    puts "BEGIN SCHEDULER at #{Time.now}"

    @url = "http://www.marktplaats.nl/z/computers-en-software/apple-ipad/ipad-mini.html?  query=ipad+mini&categoryId=2722&priceFrom=100%2C00&priceTo=&startDateFrom=always"
    @doc = Nokogiri::HTML(open(@url))
    @title = @doc.at_css("title").text

    @number = 0

    2.times do |number|
        @doc.css(".defaultSnippet.group-#{@number}").each do |listing|
            @listing_title = listing.at_css(".mp-listing-title").text
            @listing_subtitle = listing.at_css(".mp-listing-description").text
            @listing_price = listing.at_css(".price").text
            @listing_priority = listing.at_css(".mp-listing-priority-product").text

            listing = Listing.create(title: "#{@listing_title}", subtitle: "#{@listing_subtitle}", price: "#{@listing_price}")

        end

        @number +=1
    end

    puts "END SCHEDULER at #{Time.now}"
end

它不工作吗?

是的,当前设置正在运行。但是,我不知道如何通过http://www.myapp.com/interval(示例)启用更改间隔时间。

更改scheduler.every "1h"scheduler.every "#{@interval} do不起作用。

我必须在哪个文件中定义@interval它才能在其中工作task_scheduler.rb

4

2 回答 2

2

我对 Rufus Scheduler 不是很熟悉,但似乎很难用它来实现你的两个目标(定期心跳,动态重新安排)。为了使其工作,您必须捕获它返回的 job_id,如果发生重新调度事件,则使用该 job_id 停止作业,然后创建新作业。Rufus 还指出,它是一个内存中的应用程序,当进程消失时,它的作业也会消失——重新启动服务器、重新启动应用程序等,你必须从头开始重新安排。

我会考虑两件事。首先,我会考虑创建一个包含您想要执行的屏幕抓取的模型。至少您会捕获 url 和时间间隔。该模型可以将用于处理 html 响应的代码(基本上包含在 2.times 块中的内容)包装为您基于 URL 触发的实例方法。您也可以在文本列中捕获它并在其上使用 eval,假设只有“好人”才能访问系统的这一部分。这有几个优点:您可以快速扩展到抓取其他站点,并且可以清理用户发回的时间间隔。

其次,像 Delayed::Job 这样的东西可能更适合您的需求。Delayed::Job 允许您指定作业执行的时间,您可以通过读取模型并将间隔转换为时间来填写该时间。这种方法的关键是作业必须在退出之前安排其自身的下一次迭代。

这不会像 cron 那样稳定,但它似乎确实更好地解决了重新安排的需求。

于 2013-11-20T14:55:38.403 回答
1

首先:您的 rufus 调度程序代码在初始化程序中,这很好,但它在 rails 进程启动之前执行,并且在 rails 进程启动时执行。因此,在初始化程序中,您无法访问@interval可以设置的任何变量,例如在控制器中。

什么是可能的选项,而不是类变量:

  • 从配置文件中读取
  • 从数据库中读取它(但您必须设置自己的连接,在初始化程序中 activerecord 未启动 imho

而且...如果您更改该值,则必须重新启动您的 rails 进程才能使其再次生效。

因此,您的 rails 进程处理计划作业的间隔的另一种方法是使用重复的后台作业。在后台结束时,它会重新安排自己,此时的活动间隔。我建议从数据库中获取间隔。任何后台作业处理程序都可以做到这一点。检查ruby​​ 工具箱,我投票支持 resque 或 delay_job。

于 2013-11-20T14:55:45.977 回答