amazon.co.jpから注目アイテムの発売日を取り出す
Ruby/AmazonとiCalendarライブラリを使って、キーワード検索の結果から発売スケジュール表を作ってみた。
#!/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