Abcver='$Id: abc.rb,v 1.11 2006/05/07 14:06:33 waka Exp waka $'.split(" ")[2] # http://www.double-red.net/ =begin nDiary filter abc.rb(Amazon Bk1 Collaboration) bk1(http://www.bk1.co.jp) から書誌情報と書影を取得(ファイルダウンロード)、 amazon_shop フィルタ取得情報で書影がない時に書影を補完、表示する。 具体的な動作 (1)amazon_shop キーの (@ISBN:isbn) に反応。 (2)amazon_shop フィルタ動作前に bk1 から簡単な書誌情報と画像を(存在していれば)ダウンロードする。 (3)amazon_shop フィルタ動作後、amazon からの取得情報内に書影がない場合(2)の書影で補完、表示。 なお、一歩さん(http://ippo.s5.xrea.com/ndiary/)謹製の bookstore_x (http://ippo.s5.xrea.com/ndiary/inlink.html) を常用していて、 bk1 ダウンロード書影ファイルすでに存在している場合、新規取得せずにそっちを使用します(たぶん)。 設定方法(bookstore_x 常用している方は(2)以外特に設定しなくていいはず) ※必ず FILTER = 'abc' は FILTER = 'amazon_shop' の前に記述する事!!!! (1)ndiary.conf の設定 # bookstore_x と共有できる設定 CACHE_DIRECTORY = '/hoge/foo/ndiary/log/bookcache/' #キャッシュファイル格納場所 PROXY = 'proxy.hoge.com:8080' # プロキシ(使用していない場合は記述しない) # bk1の画像利用(ダウンロード)指定(画像格納フォルダ) BOOKSTORE_BK1_IMAGE = '/hoge/foo/bar/img/bk1img/' # ダウンロード位置(必須) BOOKSTORE_BK1_IMAGEURL = './' # リンク位置(htmlにはこちらが記述される)(必須) BOOKSTORE_BK1_ID = 'p-waka54821' # bk1 ブリーダー ID(適宜) # abc 独自設定(適宜) # amazon / bk1 への商品直接リンクテンプレート。記述なければデフォルト表示。 #ABC_LINK_DECORATE = '["[bk1,amz]","a タグの要素","a タグ内 title 属性の値"]' # 例 ABC_LINK_DECORATE = '<-isbn>: 【["bk1","bk1 へのリンク","<-title>(bk1)"]】【["amz","amazon へのリンク","<-title>(amazon)"]】' # ["A,"B","C"] A: bk1 or amz # B,C: B # B,C: では以下のキーワードも定義可能。 # <-isbn>: 商品の ISBN # <-isbn_nodash>: 商品の '-' なし ISBN(4-123-45678-9 = > 4123456789) # <-title>: 商品の(bk1 における)タイトル # <-bk1id>: bk1 ブリーダー ID # <-amzid>: amazon アソシエイト ID # 強制的に bk1 の画像に変更する(amazon の画像を使用しない) ABC_FORCE_REPLACE = true (2)キャッシュディレクトリ(bk1_light)作成(必須) (1)で設定した CACHE_DIRECTORY を作成、 さらにその下に 'bk1_light' というディレクトリを作成する。 (例) CACHE_DIRECTORY = '/hoge/foo/ndiary/log/bookcache/' の場合、 /hoge/foo/ndiary/log/bookcache/bk1_light を作成する。 (3))ruby ライブラリを準備する(必須) webagent (一歩さんところから取得下さい) http://ippo.s5.xrea.com/ndiary/user/lib/webagent.rb cookie (一歩さんのところから取得下さい) http://ippo.s5.xrea.com/ndiary/user/lib/cookie.rb image_size => 必須ではなくなりました(ver 1.9から) http://raa.ruby-lang.org/list.rhtml?name=image_size yaml (ruby 1.8.x では標準) =end class Module def attr_my_accessorbk1(name) module_eval %{ def #{name.id2name}() get_bk1data @#{name.id2name} end } end end class Bk1Light attr_accessor :urlSite, :searchUrl attr_accessor :isbn attr_accessor :expire attr_accessor :diary_day attr_accessor :cached_day, :cache_dir, :cache_file attr_accessor :image_dir, :image_download attr_accessor :image_width, :image_height attr_my_accessorbk1 :image_url attr_my_accessorbk1 :bibid attr_my_accessorbk1 :product_url attr_my_accessorbk1 :local_img attr_my_accessorbk1 :title def initialize @expire = 0 # 0だと存在するキャッシュを必ず使用 @image_download = false @urlSite = 'http://www.bk1.co.jp/' @diary_day = Time.now @cached_day = Time.now @flag = false @title = nil @local_img = nil @image_url = nil @image_width = nil @image_height = nil @media = nil @product_url = nil @cache_dir = "" @cache_file = "" end def load_cache begin if @flag or (File::directory?(@cache_dir.to_s) and File::readable?(@cache_dir + @cache_file) and File::mtime(@cache_dir + @cache_file).to_i < Time::now.to_i - 3600 * 24 * @expire and @expire != 0) return end rescue puts "cache_file= " + @cache_file.to_s puts $! end @flag = true read_cache end def read_cache cache_file = File.join(@cache_dir, @cache_file) if /\.txt/i =~ @cache_file return if ! FileTest.exist?(cache_file) cache = File.open(cache_file,mode="r") cache.read.to_a.each{|line| @title = $1.tosjis if /^title\t(.+?)$/ =~ line @bibid = $1 if /^id\t(.+?)$/ =~ line @isbn = $1 if /^isbn\t(.+?)$/ =~ line } cache.close else if ! FileTest.exist?(cache_file) @flag = nil return end cache = File.open(cache_file,mode="r") str = YAML::load(cache) @title = str["商品タイトル"] @product_url = str["商品URL"] @image_url = str["画像URL"] @image_width = str["画像幅"] @image_height = str["画像高さ"] @media = str["メディア"] @diary_day = str["日記記載日"] @cached_day = str["キャッシュした時間"] @isbn = str["ISBN"] @bibid = str["BIBID"] @local_img = str["ローカル画像"] # 2005/4/10 bk1 リニューアル @product_url = @product_url.to_s.gsub(/cgi-bin.+?$/,"product/#{@bibid}") cache.close end end def save_cache return if ! File::directory?(@cache_dir.to_s) cache_file = File.join(@cache_dir, @cache_file) str = Hash[\ "商品タイトル",@title,\ "商品URL",@product_url,\ "画像URL",@image_url,\ "画像幅",@image_width,\ "画像高さ",@image_height,\ "メディア",@media,\ "日記記載日",@diary_day,\ "キャッシュした時間",@cached_day,\ "ISBN",@isbn,\ "BIBID",@bibid,\ "ローカル画像",@local_img,\ "FilterVersion",Abcver\ ] cache = File.open(cache_file,mode="w") cache.write(str.to_yaml) cache.close end def get_bk1data load_cache return if @flag @searchUrl = @urlSite + "search/search.asp?kywd=#{@isbn}&Sort=dd" puts "CHK; get #{@searchUrl}" agent = WebAgent.new() agent.uri = @searchUrl getstart = Time.now begin agent.get() puts " Time: #{Time.now - getstart}(sec)" rescue puts " Time Out: #{Time.now - getstart}(sec)" return false end body = agent.body.gsub!(/[\r\n]/,"") bibid = Array.new body.scan(//){ bibid << $1 if ! $1.nil? } @bibid = bibid.first if @bibid.to_s.empty? save_cache return end body.scan(/src="\/(bookimages\/.+?#{@bibid}.+?_s.jpg)"/){ @image_url = $1.gsub(/_s/,"") if ! $1.nil? @image_url = File.join(@urlSite,@image_url) } body.scan(/#{@bibid}">(.+?)<\/font>/mi){ @title = $1.to_s } @product_url = @urlSite + "product/#{@bibid}" if @local_img.to_s.empty? if @image_download do_image_download end end @title = @title.tosjis # if @bibid.to_s.empty? if @title.to_s.empty? read_cache else save_cache @flag = true end end def do_image_download if @image_url.nil? @local_img = "" return end image_file_name = File.join(@image_dir, "isbn#{@isbn.to_s.delete('-').downcase}.jpg") #if ! FileTest.exist?(image_file_name) # キャッシュがない場合強制的にダオウンロードしたほうが便利 2006-5-10(Wed) begin agent = WebAgent.new() puts "CHK; get #{@image_url}" agent.uri = @image_url agent.get() fp = open(image_file_name, 'wb') fp.puts agent.body fp.close rescue # timeout: no image end #end if FileTest.exist?(image_file_name) if FileTest.size(image_file_name) < 1000 # ファイルサイズが 1000 byte 以下はファイル無し get_image_size @local_img = "" else @local_img = "isbn#{@isbn.to_s.delete('-').downcase}.jpg" end end end def get_image_size image_file_name = File.join(@image_dir, "isbn#{@isbn.to_s.delete('-').downcase}.jpg") if FileTest.exist?(image_file_name) # image = ImageSize.new(open(image_file_name,"r").read) # @image_width, @image_height = image.get_width.to_i, image.get_height.to_i @image_width, @image_height = ImageSize::size(image_file_name) end end end class Filter def jan2isbn(jan_code) return nil if ! (jan_code.length == 13 && jan_code =~ /^97[89]/) isbn_array = jan_code.split('')[3..-2] chk_sum = 0 isbn_array.each_with_index{|char, idx| chk_sum += (10 - idx) * char.to_i } chk_digit = 0 if chk_sum % 11 > 0 chk_digit = 11 - (chk_sum % 11) elsif chk_sum % 11 == 1 chk_digit = 'X' end isbn = isbn_array.push(chk_digit).to_s return isbn end def abc(str, type) amazon_shop_ver = '' amzshop_prefix = ['@'] @diary.filter.methods.each{|method| if /amazon_shop2/ =~ method if @diary.config['AMAZON_SHOP2_PREFIX'].to_s.empty? amzshop_prefix << '@@' else amzshop_prefix << @diary.config['AMAZON_SHOP2_PREFIX'] end break end } return if /(?:#{amzshop_prefix.join("|")})ASIN:B[0-9a-zA-Z]{9}/ =~ str# ISBN っぽくない ASIN 指定は無視する $:<< @diary.config['USER_LIB_DIRECTORY'] begin require 'cookie' require 'webagent' #require 'image_size' require 'lib/imagesize' require 'yaml' rescue LoadError puts $! end tagend = @diary.isXHTML ? ' />' : '>' bk1id, amzid = '', '' if ! @diary.config['BOOKSTORE_BK1_ID'].to_s.empty? bk1id = @diary.config['BOOKSTORE_BK1_ID'] end if ! @diary.config['BOOKSTORE_AMAZON_ID'].to_s.empty? amzid = @diary.config['BOOKSTORE_AMAZON_ID'] amzid = amzid end startFlagStr = "bk1_lightFlagStart" endFlagStr = "bk1_lightFlagEnd" case type when :P, :UL, :DL str.gsub!(/\((#{amzshop_prefix.join("|")})(ISBN|JAN|ASIN):(.+?)(\/.+?)?\)/){ prefix = $1.to_s catalog = $2.to_s codekey = $3.to_s tmptemplate = $4.to_s isbn = codekey asin = codekey if /jan/mi =~ catalog isbn = jan2isbn(codekey) asin = isbn end bk1Light = Bk1Light.new bk1Light.isbn = isbn.delete('-').downcase title = "" product_url = "" # bookstore_x のキャッシュをロードする bk1Light.cache_dir = File.join(@diary.config['CACHE_DIRECTORY'],'bk1') bk1Light.cache_file = "isbn#{bk1Light.isbn}.txt" if ! @diary.config['BOOKSTORE_BK1_IMAGE'].to_s.empty? bk1Light.image_download = true bk1Light.image_dir = @diary.config['BOOKSTORE_BK1_IMAGE'] end title = bk1Light.title.to_s product_url = bk1Light.urlSite + "search/search.asp?kywd=#{bk1Light.isbn}&Sort=dd" if title.to_s.empty? bk1Light = Bk1Light.new bk1Light.cache_dir = File.join(@diary.config['CACHE_DIRECTORY'],'bk1_light') bk1Light.isbn = isbn.delete('-').downcase bk1Light.cache_file = bk1Light.isbn if ! @diary.config['BOOKSTORE_BK1_IMAGE'].to_s.empty? bk1Light.image_download = true bk1Light.image_dir = @diary.config['BOOKSTORE_BK1_IMAGE'] end title = bk1Light.title.to_s product_url = bk1Light.product_url.to_s end retstr = "" if ! title.to_s.empty? bk1link = product_url.gsub(/\.$/,"") + "/?partnerid=" + bk1id + "/" amzlink = %Q'http://www.amazon.co.jp/exec/obidos/ASIN/#{asin.delete("-")}/#{amzid}/ref=nosim' # abc リンクテンプレート使用 if @diary.config['ABC_LINK_DECORATE'].to_s.empty? amzbk1link= %Q'ISBN: #{bk1Light.isbn}【bk1】【amazon】' else abcdecorate = @diary.config['ABC_LINK_DECORATE'].to_s.gsub(/<-isbn>/,"#{bk1Light.isbn}").gsub(/<-title>/,"#{bk1Light.title}").gsub(/<-isbn_nodash>/,"#{bk1Light.isbn}").gsub(/<-bk1id>/,bk1id).gsub(/<-amzid>/,amzid) # [bk1,amz]decorate = ["[bk1,amz]","a タグの要素","a タグ内 title 属性の値"] bk1decorate = abcdecorate.scan(/\["(bk1)","(.+?)","(.+?)"\]/).flatten amzdecorate = abcdecorate.scan(/\["(amz)","(.+?)","(.+?)"\]/).flatten amzbk1link = abcdecorate.to_s.gsub(/\["bk1.+?"\]/,%Q'#{bk1decorate[1]}').gsub(/\["amz.+?"\]/,%Q'#{amzdecorate[1]}') end # amazon_shop マイナー機能の一時的テンプレートロード時はスキップ if ! tmptemplate.to_s.empty? retstr = %Q'(#{prefix}#{catalog}:#{codekey}#{tmptemplate})#{amzbk1link}' else retstr = %Q'(#{prefix}#{catalog}:#{codekey})#{amzbk1link}' end else amzlink = %Q'http://www.amazon.co.jp/exec/obidos/ASIN/#{asin.delete("-")}/#{amzid}/ref=nosim' # abc リンクテンプレート使用 if @diary.config['ABC_LINK_DECORATE'].to_s.empty? amzbk1link= %Q'ISBN: #{bk1Light.isbn}【bk1】【amazon】' else abcdecorate = @diary.config['ABC_LINK_DECORATE'].to_s.gsub(/<-isbn>/,"#{bk1Light.isbn}").gsub(/<-title>/,"#{bk1Light.title}").gsub(/<-isbn_nodash>/,"#{bk1Light.isbn}").gsub(/<-bk1id>/,bk1id).gsub(/<-amzid>/,amzid) # [bk1,amz]decorate = ["[bk1,amz]","a タグの要素","a タグ内 title 属性の値"] bk1decorate = abcdecorate.scan(/\["(bk1)","(.+?)","(.+?)"\]/).flatten amzdecorate = abcdecorate.scan(/\["(amz)","(.+?)","(.+?)"\]/).flatten amzbk1link = abcdecorate.to_s.gsub(/\["bk1.+?"\]/,%Q'#{bk1decorate[1]}').gsub(/\["amz.+?"\]/,%Q'#{amzdecorate[1]}') end retstr = %Q'(#{prefix}#{catalog}:#{codekey})#{amzbk1link}' end retstr + "" } when :AFTER_ONEDAY if ! @diary.config['BOOKSTORE_BK1_IMAGE'].to_s.empty? image_dir = @diary.config['BOOKSTORE_BK1_IMAGE'] image_url = @diary.config['BOOKSTORE_BK1_IMAGEURL'] w,h = nil, nil str.gsub!(/(.+?)/mi){ isbn = $1.to_s body = $2.to_s bk1Light = Bk1Light.new bk1Light.isbn = isbn title = "" product_url = "" # bookstore_x のキャッシュをロードする bk1Light.cache_dir = File.join(@diary.config['CACHE_DIRECTORY'],'bk1') bk1Light.cache_file = "isbn#{isbn}.txt" title = bk1Light.title.to_s product_url = bk1Light.urlSite + "search/search.asp?kywd=#{bk1Light.isbn}&Sort=dd" if title.to_s.empty? bk1Light = Bk1Light.new bk1Light.isbn = isbn bk1Light.cache_dir = File.join(@diary.config['CACHE_DIRECTORY'],'bk1_light') bk1Light.cache_file = isbn title = bk1Light.title.to_s product_url = bk1Light.product_url.to_s end bk1link = product_url.gsub(/\.$/,"") + "/?partnerid=" + bk1id + "/" image_file = bk1Light.local_img if bk1Light.image_width.to_s.empty? || bk1Light.image_height.to_s.empty? bk1Light.image_dir = image_dir bk1Light.get_image_size bk1Light.save_cache end image_width = " width=#{bk1Light.image_width}" if bk1Light.image_width.to_i > 0 image_height = " height=#{bk1Light.image_height}" if bk1Light.image_height.to_i > 0 if FileTest.exist?(File.join(image_dir,image_file)) and FileTest.file?(File.join(image_dir,image_file)) # ↓ファイルサイズが 1000 byte 以下はファイル取得失敗している(= 画像無し)とみなす if ! (FileTest.size(File.join(image_dir,image_file)) < 1000) linkstr = %Q'' if ! @diary.config['NO_IMAGE_FILE'].to_s.empty? no_image_file = @diary.config['NO_IMAGE_FILE'].to_s body.gsub!(/#{no_image_file}/,linkstr) else body.gsub!(/No Image<\/div>/mi,linkstr) end # amazon 画像があっても強制的に bk1 の画像に変更する。 if @diary.config['ABC_FORCE_REPLACE'] #body.gsub!(//mi,linkstr) body.gsub!(%r'/mi,linkstr) end end end body } end end end end