amazon.co.jpから注目アイテムの発売日を取り出す

投稿者 akira 2006-08-14 15:00:00 GMT

Ruby/AmazoniCalendarライブラリを使って、キーワード検索の結果から発売スケジュール表を作ってみた。

#!/usr/bin/ruby -Ku
basedir = File.dirname($0)
$LOAD_PATH.unshift File.join(basedir, 'icalendar-0.97/lib')
require 'date'
require 'amazon/search'
require 'icalendar'
require 'time'
 
outfile = '*** filename ***'
devid = '*** devid ***'
keywords = [
  '*** keyword ***',
  '*** keyword ***',
  '*** keyword ***',
]
max_retry = 5
 
products = {}
req = Amazon::Search::Request.new(devid, nil, 'jp')
req.cache = Amazon::Search::Cache.new(File.join(basedir, 'cache'))
retry_count = 0
keywords.each do |keyword|
  (1..99).each do |i|
    begin
      req.keyword_search(keyword, 'books',
                         Amazon::Search::LIGHT, i).products.each do |product|
        h = product.to_h
        products[h['asin']] = h
      end
      retry_count = 0
      sleep 60
    rescue Amazon::Search::Request::SearchError
      break # done
    rescue
      $stderr.puts "#{Time.now.iso8601}: #{$!} (#{keyword})"
      retry_count += 1
      exit(1) if retry_count > max_retry
      sleep 120*retry_count
      retry
    end
  end
end
 
ical = Icalendar::Calendar.new
 
ical.custom_property('X-WR-CALNAME', '注目アイテム')
ical.custom_property('X-WR-CALDESC', '注目アイテム')
ical.custom_property('X-WR-TIMEZONE', 'Asia/Tokyo')
 
ical.timezone do
  tzid 'Asia/Tokyo'
  standard do
    tzoffsetfrom '+0900'
    tzoffsetto   '+0900'
    dtstart      '19700101T000000'
  end
end
 
today = Date.today
products.each do |asin, product|
  begin
    date = Date.parse(product['release_date'])
    next if date - today < -45
    ical.event do
      uid     "X-ASIN-#{product['asin']}"
      dtstart date
      dtend   date.next
      summary product['product_name']
      description "#{product['product_name']} (#{product['manufacturer']})
\n価格: #{product['our_price']} (定価: #{product['list_price']})
\n著者: #{product['authors'].join(', ')}
\n" klass 'PUBLIC' end rescue ArgumentError # 日付が年月日そろっていないので無視 end end File.open(outfile + '.n', 'w') do |o| o.print ical.to_ical end begin File.rename(outfile, outfile + '.o') rescue Errno::ENOENT end File.rename(outfile + '.n', outfile)

もっとましなやり方がありそうな気もする。なお、Ruby/Amazonはdebパッケージでいうところの0.9.0-2でないとリダイレクトが扱えないのでうまくなくて、かつ、sargeのruby1.8だとamazon/search.rbの945行目にある「redirects += 1」をかっこでくくっておかないとならない。というか、Ruby/Amazonの最新は0.9.2なんだな。debは古いままらしい。

あとiCalendar-0.97にはもしかするとバグがあるかも。上のスクリプトを動かすためには以下の変更が必要だった。タイムゾーンのところはコードで使わなければ必要ないがto_icalのほうは必要っぽい。ちなみにタイムゾーンのところはgoogle calendarに読み込んでもらうために試行錯誤した中で付いたもので、実は指定する必要はないのかもしれない(調べていない)。

diff -ruN icalendar-0.97.orig/lib/icalendar/component/timezone.rb icalendar-0.97/lib/icalendar/component/timezone.rb
--- icalendar-0.97.orig/lib/icalendar/component/timezone.rb	2006-04-26 17:57:42.000000000 +0900
+++ icalendar-0.97/lib/icalendar/component/timezone.rb	2006-08-15 09:47:56.000000000 +0900
@@ -20,7 +20,17 @@
   # New York City starting from 1967. Each line represents a description
   # or rule for a particular observance.
   class Timezone < Component
-    ical_component :standard, :daylight
+    def standard(&block)
+      e = Standard.new
+      self.add_component e
+      e.instance_eval &block if block
+      e
+    end
+    def daylight(&block)
+      e = Daylight.new
+      self.add_component e
+      e.instance_eval &block if block
+    end
  
     # Single properties
     ical_property :dtstart, :start
@@ -49,10 +59,12 @@
     # Also need a custom to_ical because typically it iterates over an array
     # of components.
     def to_ical
-      print_component do |s|
+      print_component do
+        s = ''
         @components.each_value do |comp|
           s << comp.to_ical
         end
+        s
       end
     end
トラックバック

トラックバックリンク:
http://arika.org/diary/trackbacks?article_id=1965