Amazon_shop2ver='$Id: amazon_shop2.rb,v 1.4 2006/10/01 13:26:25 waka Exp waka $'.split(" ")[2] =begin = amazon_shop2 - nDiary フィルタ。amazon から各種情報をゲットし、日記内に表示する Authors:: waka Version:: '$Revision: 1.4 $' License:: Ruby ライセンスに準拠 == 使い方 日記中に (@@DVD:BCBA-0618) (@@CD:AMCY-7125) みたいな (@@DVD:背表紙にある記号) (@@CD:背表紙にある記号) という形式の文字列があると、amazon(http://www.amazon.co.jp/) から 書誌、DVD,CDの情報やら書影、ジャケット画像、商品画像やらを引っ張ってきて置き換えます。 ※ フィルタ認識文字 '@@' は、設定で変更できます(後述「その他の設定」参照) == 対応商品 一部主要な商品情報取得に Amazon Web Service を利用していますので、 www.amazon.co.jp が取り扱っているすべての商品に対応しています。(たぶん) ※ @@ に続くキーワードは設定で追加できます(後述「その他の設定」参照) - CD -- (@@CD:背表紙記号もしくは ASIN) - DVD -- (@@DVD:背表紙記号もしくは ASIN) - PlayStation -- (@@PS:背表紙記号もしくは ASIN) - PlayStation2 -- (@@PS2:背表紙記号もしくは ASIN) - PSP(PlayStationPortable) -- (@@PSP:背表紙記号もしくは ASIN) - GameCube -- (@@GC:背表紙記号もしくは ASIN) - Game Boy Advance -- (@@GBA:背表紙記号もしくは ASIN) - Nintendo DS -- (@@NDS:背表紙記号もしくは ASIN) - XBOX -- (@@XBOX:背表紙記号もしくは ASIN) - 本 -- (@@ISBN:ISBN) -- (@@JAN:JAN コード) - 全商品 -- (@@ASIN:ASIN) == 仕様 ruby 1.8.x 以上でのみ動作します。 == 商品情報取得方法の選択 商品情報取得に使用している、AmazonWebService 利用方法の選択ができます ・デフォルト http://www.double-red.net/cgi-bin/aws/ という個人のサイトから Amazon の商品情報を取得します。 ・ローカル PC で自分のデベロッパートークンを使用 個人サイトからの情報取得を避ける場合、 別途 aws4as2 をインストールし、設定する事でローカルで取得ができます。 (1)デベロッパートークンを Amazon から取得(取得方法はご自身で調べてください) (2)アソシエイト ID を取得(取得方法はご自身で調べてください) (3)ruby-amazon をゲット http://raa.ruby-lang.org/project/ruby-amazon/ (3)aws4as2.rb をゲット http://www.double-red.net/software/aws4as2.rb (4)ndiary.conf に以下を追記 USER_LIB_DIRECTORY = '/dokoka/ndiary/lib' USE_AWS4AS2 = 'true' AMAZON_DEV_TOKEN = 'デベロッパートークン' (BOOKSTORE_AMAZON_TOKEN = 'デベロッパートークン' でも OK) AMAZON_ASSOCIATE_ID = 'アソシエイト ID セット' (BOOKSTORE_AMAZON_ID = 'アソシエイト ID' でも OK) (5)ruby-amazon をインストール ※インストール方法がわからない場合 ruby-amazon-x.x.x.tar.gz を展開し、 USER_LIB_DIRECTORY 内に ruby-amazon というディレクトリ作って その中へ一式(lib ディレクトリを含めば OK)を入れてください。 (6)aws4as2.rb を USER_LIB_DIRECTORY に入れる (例) USER_LIB_DIRECTORY = '/ndiary/lib' USE_AWS4AS2 = 'true' AMAZON_DEV_TOKEN = 'HOGEHOGE' AMAZON_ASSOCIATE_ID = 'FUGAFUGA' == キャッシュディレクトリについて ndiary.conf の LOG_DIRECTORY で指定したディレクトリに amazon_shop2 というディレクトリを「勝手に」生成して、取得したデータをキャッシュします == amazondvd.rb、amazon_shop.rb を利用していた方へ キャッシュの上位互換はありません。 ただし、それぞれのキャッシュディレクトリと書式が異なるので、衝突はありません。 同時使用で構いません。 設定については同一です。 特に変更するような追加設定項目は今のところありません。 書式は異なります。過去の日記への amazon_shop2 を適用するためには、 日記を全て書き直すか、 amazon_shop2 の前に一発フィルタをかまして amazon_shop2 の書式変換して運用することになります == キャッシュ保持期間(実装予定) 現在対応していません。この項目は読み飛ばしてください。 キャッシュの有効期限を指定できます。 ndiary.conf にて 変数 AMAZON_CACHE_EXPIRE に日数(正の整数)を指定してください。 (0は無期限) (例) AMAZON_CACHE_EXPIRE = '30' == プロキシ設定(必須ではない) ndiary.conf で PROXY = 'proxy.hoge.com:8080' と指定しておくと、情報取得時プロクシを経由するようになります。 == その他の設定(必須ではない) ndiary.conf にて以下の変数が使用できます - AMAZON_SHOP2_PREFIX(amazon_shop2 の書式スタート文字変更) デフォルト: '@@' (例) AMAZON_SHOP2_PREFIX = '@' - AMAZON_CATALOG(amazon_shop2 の書式追加) (例) AMAZON_CATALOG = 'CD|DVD|PS|PS2|PSP|GC|GBA|NDS|XBOX|ASIN|ISBN|JAN|OS|SPORTS' - BOOKSTORE_AMAZON_ID(Amazonアソシエイトに参加している場合に有効) (例) BOOKSTORE_AMAZON_ID = 'hogehoge-foo' - NO_IMAGE_FILE ジャケット画像がない場合に代替に表示する画像(imgタグで表記) (例) NO_IMAGE_FILE='no image' == テンプレートにより表示をカスタマイズ ndiary.conf に以下を設定 AMAZON_SHOP_TEMPLATE= true キャッシュディレクトリ(amazon_shop2)以下に"template.txt" という名前のテンプレートファイルを用意します。 === テンプレートファイルを用意 テンプレートファイルの例ここから ※行頭 "#" で始まる行はコメント扱いで、無視(スキップ)されます。 テンプレートファイルの例ここまで ["キーワード","キーワードの前に置かれる文字列","キーワードの後に置かれる文字列"] == Speial Thanks - not (のとや) さん -- http://www14.cds.ne.jp/~not/ -- nDiary本体とamazon.rbの作者 -- amazon.rb のソースに少し変更を加えたものが amazondvd.rb そこからさらに発展したものが amazon_shop.rb amazon (2006/9)仕様変更対応のため、スクラッチから書き直したのが amazon_shop2.rb - mas さん -- http://masyos.sakura.ne.jp/ -- バグ報告や動作確認、Amazonアソシエイト対応など - Ace of Diamond さん -- http://every.pobox.ne.jp/ -- Amazonアソシエイト対応コード不具合パッチなど - Tmas さん -- http://tmas.s54.xrea.com/diary/ -- JAN コード対応 - amazondvd.rb / amazon_shop.rb / amazon_shop2.rb 利用者の方々 == 注意事項 著作権がらみの情報を取得するため、 www.amazon.co.jpのアソシエイトプログラムを確認の上自己責任でご利用下さい。 =end require 'net/http' require 'cgi' require 'timeout' require 'nkf' require 'yaml' require 'fileutils' class String require 'iconv' def myescape begin CGI::escape(Iconv.conv("UTF-8", "SHIFT_JIS", self)) rescue self end end end # $DEBUG = true $DEBUG = false class AmazonShop2 attr_accessor :asin attr_accessor :isbn attr_accessor :jancode attr_accessor :book_label attr_accessor :catalog attr_accessor :cache_dir attr_accessor :proxy attr_accessor :srch_index attr_accessor :srch_keywd attr_accessor :product_name attr_accessor :manufacturer attr_accessor :authors attr_accessor :our_price attr_accessor :list_price attr_accessor :release_date attr_accessor :review attr_accessor :reviewer attr_accessor :srch_url attr_accessor :num_media attr_accessor :book_size attr_accessor :book_page attr_accessor :media attr_accessor :platform attr_accessor :platforms attr_accessor :image_url_small attr_accessor :image_url_medium attr_accessor :image_url_medium_wh attr_accessor :image_url_large attr_accessor :image_url_large_wh attr_accessor :dvd_extra_spec #形式: Color, Widescreen, Dolby など attr_accessor :dvd_region_code #リージョンコード attr_accessor :dvd_display_size #画面サイズ: 1.78:1 など attr_accessor :dvd_play_time # 再生時間 attr_accessor :directors # 監督 attr_accessor :starring # 出演者 attr_accessor :mpn #メーカー型番 attr_accessor :product_detail # 詳細仕様 attr_accessor :ruby_amz_lib attr_accessor :use_aws4as2 # 商品情報取得に aws4as2 ライブラリを使用する attr_accessor :aws_token # デベロッパートークン。use_aws4as2 true の時、必須 attr_accessor :associate_id # アソシエイト ID。use_aws4as2 true の時、必須 def initialize @asin = '' @isbn = '' @jancode = '' @book_label = '' @catalog = '' @cache_dir = '' @proxy = '' @srch_index = '' @srch_keywd = '' @product_name = '' @manufacturer = [] @authors = [] @our_price = '' @list_price = '' @release_date = '' @review = '' @reviewer = '' @srch_url = '' @num_media = '' @book_size = '' @book_page = '' @media = '' @platform = '' @platforms = [] @image_url_small = '' @image_url_medium = '' @image_url_medium_wh = [0, 0, 0] @image_url_large = '' @image_url_large_wh = [0, 0, 0] @dvd_extra_spec = '' @dvd_region_code = '' @dvd_display_size = '' @dvd_play_time = '' @directors = [] @starring = [] @mpn = '' @product_detail = '' @ruby_amz_lib = '' @use_aws4as2 = false @aws_token = '' @associate_id = '' end def save_obj newobj = Hash.new self.instance_variables.each{|instance| newobj["#{instance}"] = self.instance_variable_get(instance) } return newobj end def load_obj(obj) self.instance_variables.each{|instance| eval(%Q'#{instance} = obj["#{instance}"]') } end def save_cache(cache_file) begin obj = save_obj cache = File.open(cache_file.untaint, "w") cache.flock(File::LOCK_EX) cache.write(obj.to_yaml) cache.flock(File::LOCK_UN) cache.close rescue # end end def load_cache(cache_file) begin cache = File.open(cache_file.untaint, "r") obj = YAML::load(cache) cache.close rescue raise "load_cache error : " + $! end load_obj(obj) end def cache_dir=(dir) dir << '/' unless dir[-1,1] == '/' @cache_dir = dir end def get_imagesize(url_img) image_info = [0, 0, 0] begin require 'lib/imagesize' rescue LoadError return image_info end suffix = url_img.split(".").last begin # $stderr.puts "umask: #{File::umask}" if $DEBUG defaultumask = File::umask(022) #downloadImgFile = File.join(@cache_dir,"amazon_shop2_tmp.#{suffix}") downloadImgFile = File.join(@cache_dir, File.basename(url_img)) downloadImg = File.open(downloadImgFile.untaint,"w") downloadImg.flock(File::LOCK_EX) downloadImg.puts download(url_img, @proxy) downloadImg.flock(File::LOCK_UN) downloadImg.close w, h = ImageSize::size(downloadImgFile) # <= lib/imagesize.rb 参照。2005-6-28(Tue) w, h, fsize = [0, 0, 0] if w <= 1 || h <= 1 fsize = FileTest::size(downloadImgFile) begin #File.delete(downloadImgFile) if FileTest.exist?(downloadImgFile) FileUtils.rm_f(downloadImgFile) if FileTest.exist?(downloadImgFile) rescue # ファイル削除できなかったけど終了する事もないだろう。 $stderr.puts $!.backtrace if $DEBUG end image_info = [w, h, fsize] rescue $stderr.puts $!.backtrace if $DEBUG end return image_info end def get_detail(asin) url = %Q'http://www.amazon.co.jp/gp/product/product-details/#{asin}/' begin request_body = download(url).to_s return if request_body.to_s.empty? rescue return end product_detail_scope = request_body.dup if $DEBUG begin product_detailhtml = File.open(File.join(@cache_dir, "#{asin}product_detail.html"), "w") product_detailhtml.flock(File::LOCK_EX) product_detailhtml.puts product_detail_scope product_detailhtml.flock(File::LOCK_UN) product_detailhtml.close rescue $stderr.puts $!.backtrace end end if %r'仕様:
(.+?)
'mis =~ product_detail_scope @product_detail = $1 end end def get_review(asin) url = %Q'http://www.amazon.co.jp/gp/product/product-description/#{asin}/' begin request_body = download(url).to_s return if request_body.to_s.empty? rescue return end review_scope = '' if %r'
(.*)'mis =~ request_body review_scope = $1 end if $DEBUG begin reviewhtml = File.open(File.join(@cache_dir, "#{asin}review.html"), "w") reviewhtml.flock(File::LOCK_EX) reviewhtml.puts review_scope reviewhtml.flock(File::LOCK_UN) reviewhtml.close rescue $stderr.puts $!.backtrace end end if %r'(出版社.+?著者からの内容紹介)(.*?)<(/div|b)>'mis =~ review_scope @reviewer =$1 @review = $2 elsif %r'(内容(「.+?」データベースより))(.*?)<(/div|b)>'mis =~ review_scope @reviewer =$1 @review = $2 elsif %r'(内容紹介)(.*?)<(/div|b)>'mis =~ review_scope @reviewer = $1 @review = $2 elsif %r'(商品紹介)(.*?)<(/div|b)>'mis =~ review_scope @reviewer = $1 @review = $2 elsif %r'(メーカーより)(.*?)<(/div|b)>'mis =~ review_scope @reviewer = $1 @review = $2 elsif %r'(Book Description)(.*?)<(/div|b)>'mis =~ review_scope @reviewer = $1 @review = $2 elsif %r'(メーカー/レーベルより)(.*?)<(/div)>'mis =~ review_scope @reviewer = $1 @review = $2 elsif %r'(Amazon.co.[^<]+?商品紹介)(.*?)<(/div)>'mis =~ review_scope @reviewer = $1 @review = $2 end @reviewer = @reviewer.gsub(/<.+?>/,"").strip if ! @reviewer.empty? @review = @review.gsub(/<.+?>/,"").strip if ! @review.empty? end def download(url, proxy = nil) if /^http/ =~ url $stderr.puts "CHK; access; #{url}" require 'net/http' Net::HTTP.version_1_2 domain, port = "", "" if /\/\/(.+?)(?:\/|$)/ =~ url domain = $1.to_s end protocol = url.split(":").first + "://" path = url.gsub(Regexp.new((protocol + domain).untaint),"") if ! proxy.nil? proxy, port = proxy.split(':') port = port.to_i else proxy = port = nil end begin http = Net::HTTP::Proxy(proxy, port).new(domain.untaint, 80) file_info = nil file_info_302 = true while file_info_302 do if /1\.6/ =~ RUBY_VERSION file_info, = http.get2(path) else file_info = http.get(path) end if file_info.code.to_i == 302 path = file_info.header['location'] path.gsub!(/#{protocol}#{domain}/,"") next end file_info_302 = false # Net::HTTP のバージョン 1.2 では、Net::HTTP#get メソッドは HTTPResponse を返します。 #return file_info.response.body.gsub(/―/,"−"), path return file_info.body.gsub(/―/,"−"), path end rescue return 'net ' + $! end else return open(url, "rb").read.gsub(/―/,"−"), nil end end def get_shopdata(code_id = nil, catalog = nil) return if code_id.nil? catalog = "asin" if catalog.nil? @catalog = catalog.strip.downcase cache_file_name = File.join(@cache_dir, "#{@catalog.upcase}-#{code_id}.yml") if FileTest.exist?(cache_file_name.untaint) # && ! $DEBUG load_cache(cache_file_name.untaint) return end @srch_index = "blended" @srch_keywd = code_id @srch_url = "http://www.amazon.co.jp" platform_detail_get = false if /asin|isbn/ !~ @catalog case @catalog when "cd" #ポピュラー音楽 @srch_index = "music-jp" when "dvd" #DVD @srch_index = "dvd-jp" platform_detail_get = true when "ps", "ps2", "psp", "gc", "xbox", "gba" #TVゲーム @srch_index = "videogames-jp" platform_detail_get = true when "toys" #おもちゃ&ホビー @srch_index = "toys-jp" when "software" #ソフトウェア @srch_index = "software-jp" when "sports" #スポーツ @srch_index = "sporting-goods-jp" when "electronics" #エレクトロニクス @srch_index = "electronics-jp" when "kitchen" #ホーム&キッチン @srch_index = "kitchen-jp" when "vhs" #ビデオ @srch_index = "vhs-jp" end @srch_keywd = code_id.upcase @srch_url += %Q'/gp/search/?index=#{@srch_index}&field-keywords=#{@srch_keywd}' else code_id = code_id.delete('-') @srch_url += %Q'/exec/obidos/ASIN/#{code_id}/?val=authorized' end request_body = download(@srch_url).to_s if $DEBUG begin debug_cache_file_name = File.join(@cache_dir, "#{code_id}.html").untaint debug_cache = File.open(debug_cache_file_name.untaint, "w") debug_cache.flock(File::LOCK_EX) debug_cache.puts request_body debug_cache.flock(File::LOCK_UN) debug_cache.close rescue # end end image_scope = '' if %r'(^(?:)?.*(?:)?
.*注文した商品はどこ[??])'ms =~ request_body image_scope = $1 elsif %r'(
.+注文した商品はどこ[??])'ms =~ request_body image_scope = $1 end if /isbn|asin/i =~ @catalog @srch_keywd = @srch_keywd.delete("-") end aws_request = '' if @use_aws4as2 && (! @aws_token.empty? && ! @associate_id.empty?) begin $:<< File.join(@ruby_amz_lib,'lib') if ! $:.include?(File.join(@ruby_amz_lib,'lib')) require 'aws4as2' rescue LoadError puts $! end begin aws = Aws.new(@aws_token, @associate_id) aws.power_search(@srch_keywd) aws_request = aws.as2request.to_s rescue puts $! end else # AmazonWebService を利用し、最低限、かつ不変の情報を配信するサイトから、情報をゲット awsurl = %Q'http://www.double-red.net/cgi-bin/aws/?srch_code=#{@srch_keywd}' begin aws_request = download(awsurl, nil).to_s rescue puts $! end end aws_request.each{|line| key = line.split(",").first value = line.gsub(/^@.+?,/,"").strip case key when /^@asin/ @asin = value when /^@isbn/ @isbn = value when /^@jancode/ @jancode = value when /^@catalog/ @catalog = value when /^@media/ @media = value when /^@num_media/ @num_media = value when /^@product_name/ @product_name = value when /^@our_price/ @our_price = value when /^@list_price/ @list_price = value when /^@manufacturer/ @manufacturer = value when /^@image_url_small/ @image_url_small = value when /^@image_url_medium/ @image_url_medium = value when /^@image_url_large/ @image_url_large = value when /^@release_date/ @release_date = value when /^@authors/ @authors = value.split(",") when /^@directors/ @directors = value.split(",") when /^@platforms/ @platforms = value.split(",") when /^@starring/ @starring = value.split(",") when /^@mpn/ @mpn = value end } # リリース日が取得できなかった時 if @release_date.to_s.empty? if %r"(?:発売日[::]|\()([\d\/]+[\d])\)?
" =~ image_scope @release_date = $1 elsif %r|\((\d{4}\/[\d\/]+)\)| =~ image_scope @release_date = $1 end end # レーベル名を取得 by Tmas さん if %r'類似商品をブラウズする:' =~ image_scope if %r'#{@manufacturer} > (.+?)'m =~ image_scope @book_label = $1 end end # ゲームなどのプラットフォームゲット if /プラットフォーム:(.+?)$/ =~ request_body @platform = $1.to_s.gsub(/<.+?>/,"").gsub(/ /,"") end # 紹介文、紹介者ゲット get_review(@asin) # 詳細仕様ゲット get_detail(@asin) w, h, fsize = get_imagesize(@image_url_medium) if w.to_i > 10 && h.to_i > 10 && fsize.to_i > 0 @image_url_medium_wh = [w, h, fsize] else @image_url_medium = '' end w, h, fsize = get_imagesize(@image_url_large) if w.to_i > 10 && h.to_i > 10 && fsize.to_i > 0 @image_url_large_wh = [w, h, fsize] else @image_url_large = '' end # ディスク枚数 # @num_media = $1.gsub(/[^\d]/,"") if %r'(?:)?ディスク枚数:(?:)?(.+)
' =~ image_scope # 本サイズ @book_size = $1 if %r|サイズ\(cm\): ([^<]*)(.+?)ページ形式.+?<\/b>(.+?)リージョンコード.+?<\/b>(.+?)画面サイズ.+?<\/b>(.+?)時間.+?<\/b>(.+?)" template.flock(File::LOCK_UN) template.close rescue $stderr.puts $!.backtrace end end def gen_tmpltstr(amzinfo, symbol) tagend = (@diary.isXHTML ? ' />' : '>') amazon_srch_url = %Q'http://www.amazon.co.jp/exec/obidos' begin ret_str = amzinfo.instance_variable_get(symbol) rescue $stderr.puts $!.backtrace return '' end case symbol when /image_url_medium$/ width_m, height_m, fsize_m = amzinfo.image_url_medium_wh width_l, height_l, fsize_l = amzinfo.image_url_large_wh if width_m.to_i > 0 && height_m.to_i > 0 fsize_m = fsize_m.to_i > 0 ? ",#{fsize_m}byte" : "" fsize_l = fsize_l.to_i > 0 ? ",#{fsize_l}byte" : "" image_size_m = "(#{width_m}x#{height_m}#{fsize_m})" image_size_l = "(#{width_l}x#{height_l}#{fsize_l})" alt = %Q'alt="#{amzinfo.product_name}#{image_size_m}" width="#{width_m}" height="#{height_m}"' if width_l.to_i > 0 && height_l.to_i > 0 ret_str = %Q'' else ret_str = %Q' 0 && height.to_i > 0 ret_str = %Q'#{width}x#{height}(#{fsize} byte)' end when /product_name/ product_url = amzinfo.srch_url.gsub(/\?val=authorized/,"") # aid = @diary.config['BOOKSTORE_AMAZON_ID'].to_s.empty? ? '' : @diary.config['BOOKSTORE_AMAZON_ID'] aid = amzinfo.associate_id aid = [aid, 'ref=nosim'].join('/') product_title = %Q' title="紹介ページへジャンプ"' ret_str = %Q'#{amzinfo.product_name}' when /manufacturer/ return '' if amzinfo.manufacturer.to_s.empty? || amzinfo.catalog.to_s.empty? manufacturer = amzinfo.manufacturer.strip manufacturer_title = %Q' title="#{manufacturer} の商品"' linkurl = CGI::escapeHTML(%Q'#{amazon_srch_url}/search-handle-url/?index=#{CGI::escape(amzinfo.srch_index)}&field-keywords=#{manufacturer.myescape}') anchor = %Q'#{manufacturer}' if /book/i =~ amzinfo.catalog label = amzinfo.book_label.to_s.empty? ? '' : "(#{amzinfo.book_label})" ret_str = %Q'出版社: #{anchor}#{label}' else ret_str = %Q'メーカー: #{anchor}' end when /authors/ return '' if amzinfo.authors.to_s.empty? author_info = [] amzinfo.authors.each{|author| author.strip! url = CGI::escapeHTML(%Q'#{amazon_srch_url}/search-handle-url/index=#{CGI::escape(amzinfo.srch_index)}&field-keywords=#{author.strip.myescape}') author_info << %Q'#{author}' } ret_str = %Q'著者: #{author_info.join(",")}' when /directors/ return '' if amzinfo.directors.to_s.empty? director_info = [] amzinfo.directors.each{|director| director.strip! url = CGI::escapeHTML(%Q'#{amazon_srch_url}/search-handle-url/index=#{CGI::escape(amzinfo.srch_index)}&field-keywords=#{director.strip.myescape}') director_info << %Q'#{director}' } ret_str = %Q'監督: #{director_info.join(",")}' when /starring/ return '' if amzinfo.starring.to_s.empty? actor_info = [] amzinfo.starring.each{|actor| actor.strip! url = CGI::escapeHTML(%Q'#{amazon_srch_url}/search-handle-url/index=#{CGI::escape(amzinfo.srch_index)}&field-keywords=#{actor.myescape}') actor_info << %Q'#{actor}' } ret_str = %Q'出演: #{actor_info.join(",")}' when /review$/ return '' if amzinfo.review.to_s.empty? review_str = amzinfo.review.dup if review_str.size > 100 then review_str.gsub!(/(.{100}.+?)[ 。、].*/mi){ $1 + %Q'(...)' } end ret_str = %Q'#{review_str}' when /product_detail/ return '' if amzinfo.product_detail.to_s.empty? product_detail = amzinfo.product_detail.dup if product_detail.size > 100 then product_detail.gsub!(/<.?ul>/i,"") product_detail.gsub!(/<.?b>/i,"") product_detail.gsub!(/(.{60}.+?)<.+?>.*/mi){ $1 + %Q'(...)' } end ret_str = %Q'
    #{product_detail}
' when /num_media/ return '' if amzinfo.num_media.to_s.empty? || amzinfo.catalog.to_s.empty? if /dvd|cd|music/i !~ amzinfo.catalog ret_str = %Q'数量: #{amzinfo.num_media}' else ret_str = %Q'枚数: #{amzinfo.num_media}' end end return ret_str end def amzinfo_pretty(amzinfo) as2_template_file = File.join(amzinfo.cache_dir, 'template.txt') str = Array.new if @diary.config['AMAZON_SHOP_TEMPLATE'] && FileTest.exist?(as2_template_file) # テンプレート template = open(as2_template_file, "r").read template.tosjis.each{|line| next if /^#/ =~ line line.gsub!(/(\[.+?\])/){ eval_str = $1 symbol, before, after = eval(eval_str) value = '' if amzinfo.instance_variables.include?(symbol) value = amzinfo.instance_variable_get(symbol) end begin value = gen_tmpltstr(amzinfo, symbol) next if value.to_s.empty? before + value + after if ! value.to_s.empty? rescue # end } line.chop! str << line if ! line.empty? } gen_template_file(amzinfo, str.join("\r\r")) return end # amazon_shop2 デフォルト表示の時は強制でケツに
タグ付与する info_str = Array.new # あとでまとめて join するので、Array # 商品画像 image_str = gen_tmpltstr(amzinfo, "@image_url_medium") # 商品名 product_anchor = gen_tmpltstr(amzinfo, "@product_name") if amzinfo.platform.to_s.empty? info_str << %Q'『#{product_anchor}』#{amzinfo.media.empty? ? amzinfo.catalog : amzinfo.media}' + @diary.tag_br else info_str << %Q'『#{product_anchor}』#{amzinfo.platform}' + @diary.tag_br end # 会社名 if ! amzinfo.manufacturer.empty? # 会社名 info_str << gen_tmpltstr(amzinfo, "@manufacturer") + @diary.tag_br end # 著者 if ! amzinfo.authors.to_s.empty? info_str << gen_tmpltstr(amzinfo, "@authors") + @diary.tag_br end # 監督 if ! amzinfo.directors.to_s.empty? info_str << gen_tmpltstr(amzinfo, "@directors") + @diary.tag_br end # 出演者 if ! amzinfo.starring.to_s.empty? info_str << gen_tmpltstr(amzinfo, "@starring") + @diary.tag_br end # 発売日、価格、ディスク枚数をまとめて表示 r, p, s, pg = nil,nil,nil,nil r = %Q'発売日: #{amzinfo.release_date}' if ! amzinfo.release_date.empty? p = %Q'価格: #{amzinfo.our_price}' if ! amzinfo.our_price.empty? pg = %Q'#{amzinfo.book_page}ページ' if ! amzinfo.book_page.empty? s = %Q'サイズ: #{amzinfo.book_size}cm' if ! amzinfo.book_size.empty? s = %Q'#{gen_tmpltstr(amzinfo, "@num_media")}' if ! amzinfo.num_media.to_s.empty? rps = [r,pg,p,s] rps.delete_if{|x| x.nil?} info_str << rps.join(", ") + @diary.tag_br # DVD のスペックをまとめて表示 r, p, s = nil,nil,nil,nil r = %Q'形式: #{amzinfo.dvd_extra_spec}' if ! amzinfo.dvd_extra_spec.empty? p = %Q'画面サイズ: #{amzinfo.dvd_display_size}' if ! amzinfo.dvd_display_size.empty? s = %Q'時間: #{amzinfo.dvd_play_time}' if ! amzinfo.dvd_play_time.empty? rps = [r,p,s] rps.delete_if{|x| x.nil?} info_str << rps.join(", ") + @diary.tag_br # 商品レビュー if ! amzinfo.reviewer.empty? && ! amzinfo.review.empty? info_str << %Q'【#{amzinfo.reviewer}】' + @diary.tag_br info_str << gen_tmpltstr(amzinfo, "@review") + @diary.tag_br end # 詳細スペック if ! amzinfo.product_detail.to_s.empty? info_str << gen_tmpltstr(amzinfo, "@product_detail") + @diary.tag_br end str << %Q'\t
' str << %Q'\t\t' str << %Q'\t\t\t' str << %Q'\t\t\t\t' str << %Q'\t\t\t\t' str << %Q'\t\t\t' str << %Q'\t\t
#{image_str}' str << %Q'\t\t\t\t\t#{info_str.join("\r\r")}' str << %Q'\t\t\t\t
' str << %Q'\t
' str = str.join("\r\r").to_s.gsub(/^ +\n/m,"") gen_template_file(amzinfo, str) end def amazon_shop2(str, type) amzinfo = AmazonShop2.new amzinfo.cache_dir = File.join(@diary.logDirectory, 'amazon_shop2') # $stderr.puts "umask: #{File::umask}" if $DEBUG File.umask(022) FileUtils.mkdir_p(amzinfo.cache_dir) if ! FileTest.exist?(amzinfo.cache_dir) # $stderr.puts "cache dir mode : #{File.stat(amzinfo.cache_dir).mode}" if $DEBUG File.chmod(16877,amzinfo.cache_dir) amzinfo.proxy = @diary.config['PROXY'].to_s.empty? ? '' : @diary.config['PROXY'] amzshop2_key = 'CD|DVD|PS|PS2|PSP|GC|GBA|NDS|XBOX|ASIN|ISBN|JAN|MAGAZINE' amzshop2_key = @diary.config['AMAZON_CATALOG'] if ! @diary.config['AMAZON_CATALOG'].to_s.empty? amzshop2_prefix = '@@' amzshop2_prefix = @diary.config['AMAZON_SHOP2_PREFIX'] if ! @diary.config['AMAZON_SHOP2_PREFIX'].to_s.empty? # 商品情報取得に aws4as2 を使うか? amzinfo.use_aws4as2 = true if /^true$/i =~ @diary.config['USE_AWS4AS2'].to_s if amzinfo.use_aws4as2 user_lib = @diary.config['USER_LIB_DIRECTORY'].to_s if ! user_lib.empty? $: << user_lib if ! $:.include?(user_lib) end ruby_amz = (File.join(user_lib,"ruby-amazon","lib")) $: << ruby_amz if ! $:.include?(ruby_amz) end # デベロッパートークンセット # BOOKSTORE_AMAZON_TOKEN か、AMAZON_DEV_TOKEN どちらかを受付ける。 amzinfo.aws_token = @diary.config['BOOKSTORE_AMAZON_TOKEN'].to_s.empty? ? '' : @diary.config['BOOKSTORE_AMAZON_TOKEN'] if amzinfo.aws_token.empty? && ! @diary.config['AMAZON_DEV_TOKEN'].to_s.empty? amzinfo.aws_token = @diary.config['AMAZON_DEV_TOKEN'].to_s end # アソシエイト ID セット # BOOKSTORE_AMAZON_ID か、AMAZON_ASSOCIATE_ID どちらかを受付ける。 amzinfo.associate_id = @diary.config['BOOKSTORE_AMAZON_ID'].to_s.empty? ? '' : @diary.config['BOOKSTORE_AMAZON_ID'] if amzinfo.associate_id.empty? && ! @diary.config['AMAZON_ASSOCIATE_ID'].to_s.empty? amzinfo.associate_id = @diary.config['AMAZON_ASSOCIATE_ID'].to_s end case type when :P templateF = '' str.gsub!(/\(#{amzshop2_prefix}(#{amzshop2_key}):(.+?)(\/.+?)?\)/i){ catalog = $1 asin = $2 begin # ここで失敗すると何も表示されないので致命的 amzinfo.get_shopdata(asin, catalog) rescue raise "get_shopdata error : " + $!.backtrace end amzinfo_pretty(amzinfo) templateF = File.join(amzinfo.cache_dir, "#{amzinfo.asin}.html") newstr = '' if FileTest.exist?(templateF) template = File.open(templateF, "r") newstr = template.read template.close else $stderr.puts "Not Found : #{templateF}" end newstr.chop! } # 後始末 begin FileUtils.rm_f(templateF) if FileTest.exist?(templateF) rescue # 削除に失敗しても気にするな $stderr.puts $!.backtrace end str when :HTML str.gsub!("\r\r","\n") str.gsub!(/\s*<\/p>/mi, '') str end end end