IKEAの在庫情報をRubyで取り出す


概要

IKEA在庫管理のURLから取得したXMLを処理して情報を抽出します。簡単。

背景

最近、巷で人気(多分今も)のIKEAのサメが欲しかったが、在庫はいつも品切れ・・・今日も在庫確認の為にサイトをポチポチ・・・
ある日手が滑ってたまたまChromeの検証を押してしまいたまたまNetworkを見てたらIKEAの製品の在庫数がわかるURLを発見したので、IKEAのサメの在庫監視サイトを作りました。題してIKEAの在庫わかる君

作ってみる

事前準備

nokogiriをインストール(rails環境なら既にある)
$ gem install nokogiri

とりあえずサンプル

ここのIKEAのサメの在庫情報にアクセスするとこんな感じでXMLが得られます。

CLIで在庫情報や次回入荷日(再補充日?)を抽出します

ikea.rb
require 'nokogiri'
require 'open-uri'
# url末尾の8桁の数字は商品番号
url = 'https://www.ikea.com/jp/ja/iows/catalog/availability/10373589'

xml = Nokogiri::XML(open(url).read)

STORE_NAME = { "447" => "船橋", "448" => "港北", "887" => "新三郷",
               "486" => "神戸", "392" => "仙台", "509" => "長久手",
               "496" => "鶴浜", "189" => "福岡新宮", "359" => "立川" }

# XMLのルートのノードから探して一致したNodeSetオブジェクトを返す→9店舗分のlocalStoreを取得
item_nodes = xml.xpath('//availability/localStore')

item_nodes.each do |item|
  # attribute('xx')でlocalStoreのxx属性の属性値を取得
  store_code = item.attribute('buCode').text
  puts "店名:#{STORE_NAME[store_code]}(#{store_code})"
  # localStore以下のstockノードを探してNodeSetで返す
  item.xpath('stock').each do |store|
    puts '在庫数:' + store.xpath('availableStock').text
    if store.xpath('restockDate').any?
      puts '次回入荷日:' + store.xpath('restockDate').text
    else
      puts '次回入荷日:不明'
    end
  end
  puts "-------------------------"
end

動かしてみる

できた!!

簡単に解説

open(url).readでurlのレスポンスのボディ部分を文字列で取得

Nokogiri::XML(open(url).read)でボディ部分の文字列から
Nokogiri::XML::Documentオブジェクトを生成

xml.xpath('//availability/localStore')Nokogiri::XML::NodeSetという配列のようなオブジェクトを取得。これで処理したい対象のデータ達を抽出できた

また、xpathメソッドの使い方は、今回のようにxpath('//hoge')で大元からデータを探し、NodeSetオブジェクトに対しさらにxpath('piyo')をすると、一段下のpiyo要素が得られる

NodeSetの中にはNokogiri::XML::Elementオブジェクトが格納されている

> item_nodes[1].class
=> Nokogiri::XML::Element

Elementオブジェクトに対してattribute('buCode')で属性名と属性が格納されたAttrオブジェクトを取得し、Attrにtextメソッドを呼び出すと属性値が取り出せる

> item_nodes[1].attribute('buCode')
=> #(Attr:0x3663e58 { name = "buCode", value = "448" })
> item_nodes[1].attribute('buCode').text
=> "448" #店舗コード

同様に、Elementにtextメソッドを呼び出すとタグ内の値を呼び出せる

> item_nodes[0].xpath('stock')[0].xpath('availableStock').text
=> "73" #執筆時のIKEA船橋店のサメの在庫数

終わりに

後でQiitaで検索してみるとIKEAの在庫確認している記事がけっこう見つかりました。考えることは一緒ですね。
そして自分は未だにIKEAのサメをお迎えできていません。。。

10/28日追記

この前IKEAのサメちゃんをおうちに迎え入れることができました🦈🎉

参考サイト

https://dev.classmethod.jp/tool/xmlnokogiri-xml-parse/
http://d.hatena.ne.jp/fre_oik/20110609/1307627018