価格.comのAPIを使って検索するモジュール。

すでに作られている方がいるけど、お勉強のために自分の今現在持っている知識で書いた。

require 'open-uri'
require 'rexml/document'

module KakakuAPI
  BASE_URL = 'http://api.kakaku.com/Ver1/ItemSearch.asp'

  class KakakuItem
    include Comparable

    attr_reader:product_id
    attr_reader:product_name
    attr_reader:maker_name
    attr_reader:category_name
    attr_reader:pv_ranking
    attr_reader:image_url
    attr_reader:item_page_url
    attr_reader:bbs_page_url
    attr_reader:review_page_url
    attr_reader:lowest_price
    attr_reader:num_of_bbs

    def initialize(result)
      @product_id = result.elements['ProductID'].get_text
      @product_name = result.elements['ProductName'].get_text
      @maker_name = result.elements['MakerName'].get_text
      @category_name = result.elements['CategoryName'].get_text
      @pv_ranking = result.elements['PvRanking'].get_text
      @image_url = result.elements['ImageUrl'].get_text
      @item_page_url = result.elements['ItemPageUrl'].get_text
      @bbs_page_url = result.elements['BbsPageUrl'].get_text
      @review_page_url = result.elements['ReviewPageUrl'].get_text
      @lowest_price = result.elements['LowestPrice'].get_text
      @num_of_bbs  = result.elements['NumOfBbs'].get_text
    end

    def <=>(rakuten_item)
      return self.product_id <=> rakuten_item.product_id
    end
  end

  class KakakuItems < Array
    attr_accessor:num_of_result
  end

  class ItemNotFoundError < Exception; end;
  class TooManyItemRequestedError < Exception; end;
  class InvalidParameterValueError < Exception; end;
  class InternalServerErrorError < Exception; end;
  
  def self.search(keyword, options = nil)

    param = self.create_param(keyword, options)
    url = URI.escape("#{BASE_URL}?#{param}")

    kakaku_items = KakakuItems.new
    open(url) do |result|

      product_info = REXML::Document.new(result.read).root

      # エラー発生
      if product_info.name == 'Error'
        message = product_info.elements['Message'].get_text.to_s
        message.strip!
        case message
        when 'InvalidParameterValue'
          raise(InvalidParameterValueError.new)
        when 'TooManyItemsRequested'
          raise(TooManyItemsRequestedError.new)
        when 'ItemNotFound'
          raise(ItemNotFoundError.new)
        when 'InternalServerError'
          raise(InternalServerError.new)
        else
          raise('aaa')
        end
      end

      num_of_result = product_info.elements['NumOfResult'].get_text

      kakaku_items.num_of_result = num_of_result

      product_info.each_element('Item') do |elem|
        kakaku_item = KakakuItem.new(elem)
        kakaku_items << kakaku_item
      end

    end

    return kakaku_items
  end
  
  private
  def self.create_param(keyword, options = nil)
    if keyword == nil or keyword.empty?
      raise(ArgumentError.new('keyword'))
    end

    param = ""
    param << "Keyword=#{keyword}"

    unless options[:category_group] == nil
      param << "&CategoryGroup=#{options[:category_group]}"
    end

    unless options[:sort_order] == nil
      param << "&SortOrder=#{options[:sort_order]}"
    end

    unless options[:page_num] == nil
      param << "&PageNum=#{options[:page_num]}"
    end

    return param
  end

end

使ってみる。

items = KakakuAPI.search("MacBook", {:category_group => 'Pc'})
items.each do |item|
  puts item.product_name
end

結果。

MacBook 2000/13.3 MA700J/A
MacBook 2000/13.3 MA701J/A
MacBook 1830/13.3 MA254J/A
MacBook Pro 2330/15.4 MA610J/A
MacBook Pro 2160/15.4 MA609J/A