Ruby on Rails存储代码以在数据库中执行

时间:2015-07-02 13:46:37

标签: ruby-on-rails ruby postgresql web-scraping eval

我的数据库中有一个模型Shop,它总结了我想知道的关于商店的所有内容(nameurlprice

我想就一下处理我的情况的最佳方法提出一些建议。 基本上,我想要的是废弃网站(没有API)以获得页面上显示的价格。

例如,让我们说每次用户每次访问页面X时都希望从此page获取价格,并且每次来page页面Y等等1000多页。

我的数据库中的Shops将是:

Shop #1 : {:name => "Tshirt", :url => "XXXXX", :price => "PRICE_FROM_THE_URL"}
Shop #2 : {:name => "Veste", :url => "XXXXX", :price => "PRICE_FROM_THE_URL"}

每次用户询问时,我都会看到两个更新价格的选项:

  1. 存储代码以更新数据库中的价格,并在每次需要时对其进行评估。类似于,添加列code并执行price = eval(Shop.code)
  2. 根据商店ID在我的模型上调用操作。像self.id
  3. 那样的开关盒

    我尝试了两种选择。两者都按预期工作,但我担心的是选项#1看起来像"丑陋"一个但更容易维护,而如果您有1000多个商店要记录并且每个人都有不同的报废方法,则选项#2不合适。我最终会遇到成千上万的代码行,这将无法理解。

1 个答案:

答案 0 :(得分:0)

Nokogiri允许您按css selectors抓取内容。 了解这一点,考虑以下设计指南:

  1. 使用指定商店的选择器创建一个模型,命名为:ShopSelectorGroup(它也可以创建为ActiveRecord模型,用于在数据库中存储选择器)。

    class ShopSelectorGroup
      attr_accessor: :price_selector, :other_selector, :shop_name
    end
    
  2. 然后创建一个类Scraper,它将通过注入ShopSelectorGroup类的实例进行配置。

    require 'nokogiri'
    require 'open-uri'
    
    class Scraper
      def initialize(selector_group)
        @selector_group = selector_group
      end
    
      def scrape(url)
        open(url) do |content|                        
          Nokogiri::HTML(content).css(@selector_group.price_selector).each do |data|
            yield data
         end
        end
      end
    end
    
  3. 使用方法如下:

    selector_group = ShopSelectorGroup.new
    selector_group.price_selector = 'span.price'
    # or when used as ActiveRecord model
    # selector_group = ShopSelectorGroup.findByShopName('MyShop')
    
    scraper = Scraper.new(selector_group)
    scraper.scrape(url) do |data|
      p data
      # or persist data in database
    end
    
  4. 希望这有帮助!