#!/usr/bin/env ruby Webnailver='$Id: webnail.rb,v 1.10 2005/05/15 13:57:20 waka Exp waka $'.split(" ")[2] # http://www.double-red.net/ =begin nDiary filter 指定した url の表示イメージサムネイルを取得、表示する OUTPUT_DIRECTORY で指定したディレクトリに 'webnail' というディレクトリを用意し、 日記内に webnail(url タイトル) などと記述すると url の画像をキャプチャしてサムネイルを表示し、url へのリンクを張る サムネイル画像は webnail ディレクトリに tn_date_url.png のようなファイル名で保存される。 以上が基本。 あれこれポップアップ導入している場合、ndiary.conf に WEBNAIL_WITH_AP = true と指定する、もしくはタイトルの後ろに " ap"と指定するとバナーポップアップに サムネイルを使用するようになり、ブラウザ表示上サムネイル画像は見えなくなる。 例 webnail(url タイトル ap) あれこれポップアップ http://www.remus.dti.ne.jp/~a-satomi/bunsyorou/ArekorePopup.html サムネイルと大きな画像両方を取得する。 例 webnail(url タイトル large) と記述することでサムネイルと実際の大きさのキャプチャイメージが取得される。 その他、ndiary.conf にて以下の変数が設定できます。 デフォルト動作が気に入らない場合変更下さい。 WEBNAIL_GET_LARGE = true # true で大きい画像もキャプチャ。デフォルトは false。 WEBNAIL_TIME_OUT = 10000 # webnail2.exe のタイムアウト時間(単位:ms)。windows のみ有用 WEBNAIL_TN_HEIGHT = 200 # サムネイル画像の高さ。デフォルトは 200。 WEBNAIL_TN_WIDTH = 150 # サムネイル画像の幅。デフォルトは 150。 WEBNAIL_MENUBUTTON_HEIGHT = 153 # ブラウザの装飾部分の高さ。PC-UNIX のみ有用。 以下は、Windows ユーザ向け。 他のブラウザのイメージキャプチャしたい人は、 Winshot (http://www.woodybells.com/winshot.html)と ImageMagick (http://www.imagemagick.org/)をインストールし、 WEBNAIL_USE_WS = true として下さい。 他にも以下の設定が必要。 WEBNAIL_WIN_SHOT = 'WinShot.exe のフルパス' WEBNAIL_BROWSER = 'web ブラウザのフルパス' WEBNAIL_WIN_CONVERT = 'ImageMagick convert.exe のフルパス' 例) WEBNAIL_USE_WS = true WEBNAIL_WIN_SHOT = 'c:/Program Files/WinShot/WinShot.exe' WEBNAIL_WIN_BROWSER = 'c:/Program Files/Mozilla Firefox/firefox.exe' WEBNAIL_WIN_CONVERT = 'c:/Program Files/ImageMagick/convert.exe' 以下の環境で動作する事を確認(2004-03-22 現在) [PC-UNIX] Vine Linux 2.6r1 firefox 0.8 ImageMagick-5.2.9-0vl6 [Windows] Windows XP ruby - mswin版 1.8.1 (http://www.dm4lab.to/~usa/ruby/) - cygwin版 1.8.1 (http://ftp.ruby-lang.org/pub/ruby/binaries/cygwin/1.8/) webnail2.exe (http://www.hirax.net/cgi-bin/wiki.cgi?Webnail2) webnail2 を使わない場合以下が必要 winshot (http://www.woodybells.com/winshot.html) ImageMagick (http://www.imagemagick.org/) ※ ftp://ftp.imagemagick.org/pub/ImageMagick/binaries/ ImageMagick-5.5.7-Q8-windows-dll.exe で確認。 ================================================== Windows での動作確認方法 ================================================== 以下 cygwin 前提で説明 ※コマンドプロンプトから ruby と webnail2 が起動できればよし 0.準備 パスの通った場所に webnail2.exe を置く cygwin のターミナルを起動し、 > webnail2.exe で webnail2 が起動すれば O.K. 1.確認 1-1. cygwin のターミナルを起動し、 当フィルタ (webnail.rb) を置いたディレクトリに移動 1-2. > ruby webnail.rb http://www.google.com にて webnail2.exe が起動し、カレントディレクトリに tn_www_google_coml.jpg が出来ていれば成功。nDiary フィルタとしても動作するはず。 ================================================== PC-UNIX(Windows 以外の OS)での動作確認方法 ================================================== 当フィルタ (webnail.rb) を置いたディレクトリに移動。 > ruby webnail.rb http://www.google.com にて firefox が起動し、カレントディレクトリに tn_www_google_coml.png が出来ていれば成功。nDiary フィルタとしても動作するはず。 ブラウザが起動しない場合、 クラス Webnail において、 @browserName = "Mozilla Firefox" # Window ID 特定用 @browser = "/usr/local/firefox/firefox" # ブラウザフルパス をご自分の環境に変更して下さい。 @browserName は、空ページ(about:blank)を開いた時の Window の名前 =end require 'cgi' class String def escapeSpace self.gsub(/\\/,'/').gsub(/ /,'\\ ') end end class Webnail attr_accessor :out_dir attr_accessor :usewinShot attr_accessor :image_prefix attr_accessor :menubutton_h attr_accessor :tn_w attr_accessor :tn_h attr_accessor :get_large attr_accessor :timeout attr_accessor :browser def initialize(url) # Windows / PC-UNIX 共通 @url = url @tn = false @out_dir = "" @image_prefix= "" @full_image = "" @tn_image = "" @image = "" @tn_w = 200 @tn_h = 150 @get_large = false # Windows(webnail2.exe / Winshot.exe) 用 @timeout = 5000 @usewinShot = false @winShot = 'c:/Program Files/WinShot/WinShot.exe' # WinShot のフルパス @winBrowser = 'c:/Program Files/Mozilla Firefox/firefox.exe' @winConvert = 'c:/Program Files/ImageMagick-5.5.3-Q16/convert.exe' # ImageMagick convert コマンドのフルパス # PC-UNIX 専用 # @processName = "firefox-bin" @browserName = ["Mozilla Firefox","Deer Park"] # Window ID 特定用ブラウザ名リスト @browser = "/usr/bin/firefox" # ブラウザフルパス @user = ENV["USER"] @blankpage = "about:blank" @winid, @width, @height = "","","" @winrootid = "" @large_w,@large_h = @tn_w * 4 , @tn_h * 4 @scrollbar_w = 14 # スクロールバーの幅 @menubutton_h= 90 # メニュー + ボタン類の高さ @statusbar_h = 36 # ステータスバーの高さ # @google_bar_h = 35 # @tab_h = 28 end def webnail2 case PLATFORM when /win/i imageInfo if @usewinShot then openResizedBrowser pid = fork{ exec(@winBrowser, @url) } sleep @timeout.to_i / 1000 pwd_stack = Dir.pwd Dir.chdir(@out_dir) $stderr.puts "winshot start..." `#{@winShot.escapeSpace} -J -R 100x100 -F #{@full_image} -A -X` $stderr.puts "convert (large => thumbnail) start..." $stderr.puts %Q!#{@winConvert.escapeSpace} -geometry #{@tn_w}x#{@tn_h} -quality 100 #{@full_image} #{@tn_image}! `#{@winConvert.escapeSpace} -geometry #{@tn_w}x#{@tn_h} -quality 100 #{@full_image} #{@tn_image}` Dir.chdir(pwd_stack) begin Process.kill(:TERM,pid) rescue # end else site_txt = "sites.txt" settingfile = File.open(File.join(@out_dir , site_txt),"w") settingfile.puts @url + ',' + @tn_image settingfile.close if @get_large then @get_large = "y" else @get_large = "n" end pwd_stack = Dir.pwd Dir.chdir(@out_dir) $stderr.puts "webnail2.exe start ..." system("webnail2.exe #{site_txt} #{@tn_w} #{@tn_h} #{@timeout} #{@get_large}") if @get_large == "y" then File.rename("big" + @tn_image, @full_image) end Dir.chdir(pwd_stack) end when /linux/i imageInfo browserReady sleep 0.5 if @get_large then fullsizeCapture end thumbnailCapture end end def browserReady openResizedBrowser waitDisplay $stderr.puts "open URL #{@blankpage}" openUrl(@blankpage) sleep 0.5 getWindowInfo # @winid, @width, @height = getWindowInfo openUrl(@url) waitDisplay @crop_w = @width.to_i - @scrollbar_w @crop_h = @height.to_i - (@menubutton_h + @statusbar_h) @crop_offset = "+0+#{@menubutton_h}" end def imageInfo case PLATFORM when /win/i @full_image = @image_prefix + ".jpg" @tn_image = "tn_" + @image_prefix + ".jpg" when /linux/i @full_image = @image_prefix + ".png" @tn_image = "tn_" + @image_prefix + ".png" end return @tn_image,@full_image end def fullsizeCapture @image = @full_image captureXwin end def thumbnailCapture @tn = true @image = @tn_image captureXwin end def openResizedBrowser openUrl = "" case PLATFORM when /win/i =begin resizeHtml = File.open(File.join(ENV["TEMP"],"_resize.html"),"w") resizeHtmlStr = "" resizeHtmlStr += %Q!! resizeHtmlStr += %Q!! resizeHtmlStr += %Q!! resizeHtmlStr += %Q!! resizeHtmlStr += %Q!resize! resizeHtmlStr += %Q!! resizeHtmlStr += %Q!! resizeHtmlStr += %Q!! resizeHtmlStr += %Q!! resizeHtmlStr += %Q!! resizeHtml.puts resizeHtmlStr resizeHtml.close =end resizeHtml = File.join(ENV["TEMP"],"_resize.html") resizeHtmlgen(resizeHtml) $stderr.puts "open browser with target url ..." pid = fork{ exec(@winBrowser,`cygpath -w $TEMP/_resize.html`) } #sleep 1 #system(@winBrowser,`cygpath -w $TEMP/_resize.html`) when /linux/i proc = `ps -U #{@user} -u #{@user}` if /#{File.basename(@browser)}/ !~ proc # $stderr.puts "#{@browser} -P capture &" # system("#{@browser} -P capture &") system("#{@browser} &") waitDisplay end $stderr.puts "open browser with target url ..." resizeHtml = "/var/tmp/webnail_resize.html" resizeHtmlgen(resizeHtml) #system("#{@browser} -remote openURL\\(Javascript:resizeTo\\(900,810\\)\\) openURL\\(Javascript:moveTo\\(0,0\\)\\)") #cmd = "#{@browser} -remote openURL\\(Javascript:resizeTo\\(#{@large_w + @scrollbar_w},#{@large_h + @menubutton_h + @statusbar_h}\\)\\) openURL\\(Javascript:moveTo\\(0,0\\)\\)" cmd = "#{@browser} #{resizeHtml}" puts "" puts cmd puts "" system(cmd) end end def resizeHtmlgen(html) resizeHtml = File.open(html,"w") resizeHtml.puts %Q'' resizeHtml.close end def openUrl(url) system("#{@browser} -remote openURL\\(\'#{url}\'\\)") end def getWindowInfo $stderr.puts "get xwininfo ..." # about:blank なページでないとダメ _browserName = "" while _browserName = @browserName.shift xwininfo = nil #xwininfo = `xwininfo -int -name "#{@browserName}"` xwininfo = `xwininfo -int -name "#{_browserName}"` break if ! xwininfo.to_s.empty? end puts "="*50 puts _browserName = "" puts xwininfo puts "="*50 xwininfo.each{|line| if /Window id: ([0-9]+)/ =~ line then # @winrootid = $1 @winid = $1 end if /Width: ([0-9]+)/ =~ line then @width = $1 end if /Height: ([0-9]+)/ =~ line then @height = $1 end } $stderr.puts [@winid,@winrootid,@width,@height].join(" ") =begin xwininfo = `xwininfo -int -name "#{@browserName}"` winid,width,height = "","","" xwininfo.each{|line| if /Window id: ([0-9]+)/ =~ line then winid = $1 end if /Width: ([0-9]+)/ =~ line then width = $1 end if /Height: ([0-9]+)/ =~ line then height = $1 end } =end end def waitDisplay monitor_line = 10 wait_time = 18 top_cmd = "top -b -n 1 -d 1 | grep #{@user} | head -#{monitor_line}" top_result = `#{top_cmd}` start = Time.now $stderr.puts "now waiting ..." while /#{File.basename(@browser)}/ =~ top_result top_result = `#{top_cmd}` if (Time.now - start).to_i > wait_time then break end end end def captureXwin geometry , quality = Array.new(2,""), Array.new(2,"") if @tn then tmpFile = "/var/tmp/nd_webnail.png" + $$.to_s geometry = ["-geometry","#{@tn_w}x#{@tn_h}"] quality = ["-quality","100"] $stderr.puts "capture from xwin (thumbnail)..." cmd = "import -window #{@winid} -crop #{@crop_w}x#{@crop_h}#{@crop_offset} #{quality.first} #{quality.last} -silent #{tmpFile}" system(cmd) cmd = "convert #{tmpFile} #{geometry.first} #{geometry.last} #{quality.first} #{quality.last} #{@out_dir}#{@image}" system(cmd) File.delete(tmpFile) else $stderr.puts "capture from xwin ..." cmd = "import -window #{@winid} -crop #{@crop_w}x#{@crop_h}#{@crop_offset} #{geometry.first} #{geometry.last} #{quality.first} #{quality.last} -silent #{@out_dir}#{@image}" system(cmd) end #system("import","-window","#{@winid}","-crop","#{@crop_w}x#{@crop_h}#{@crop_offset}","#{geometry.first}","#{geometry.last}","#{quality.first}","#{quality.last}","-silent",@out_dir + @image) # ダミーキャプチャ @winrootid 対象に import コマンドたたくと前面に持ってきてくれる #system("import","-window","#{@winrootid}","-silent","temp.jpg") #File.delete("temp.jpg") if File.exist?("temp.jpg") # 掃除 #getXwinID # メニューなど装飾部以外をキャプチャ #p @crop_h p @crop_h #puts @winid #system("import","-window","#{@winid}",geometry.first,geometry.last,quality.first,quality.last,"-silent",File.join(@out_dir, @image)) end def getXwinID #0x1800029 "Google - Mozilla Firefox": ("Mozilla" "navigator:browser") 900x810+0+0 +177+56 # @browserName = `xwininfo -tree -root | grep -i mozilla | grep "navigator:browser"`.scan(/"(.+)":/).to_s `xwininfo -tree -root`.each{|line| if /"navigator:browser"/ =~ line @browserName = line.scan(/"(.+)":/).to_s break end } xwininfo = `xwininfo -tree -name "#{@browserName}"` xwininfo.each{|line| if /(0x[0-9a-zA-Z]+?) /i =~ line then @winid = $1 end } end # def killBrowser # begin # `killall #{@processName}` # rescue # nil # end # end # end class Filter def webnail(str, type) webnail_dir = @diary.outputDirectory + 'webnail/' case type when :P, :UL, :DL use_inlineimage = false use_inlineimage_ex = false @diary.filter.methods.each{|m| if /inlineimage.*/ =~ m use_inlineimage = true use_inlineimage_ex = true if /_ex/ =~ m end } str.gsub!(/webnail\((.+?) (.+?)(( ap)| large)?\)/){ url = CGI::unescapeHTML($1) ret_str = "" alt = $2 ap = $3 capture = Webnail.new(url) capture.out_dir = webnail_dir if @diary.config['WEBNAIL_MENUBUTTON_HEIGHT'] then capture.menubutton_h = @diary.config['WEBNAIL_MENUBUTTON_HEIGHT'] end if @diary.config['WEBNAIL_TN_HEIGHT'] then capture.tn_h = @diary.config['WEBNAIL_TN_HEIGHT'] end if @diary.config['WEBNAIL_TN_WIDTH'] then capture.tn_w = @diary.config['WEBNAIL_TN_WIDTH'] end if @diary.config['WEBNAIL_TIME_OUT'] then capture.timeout = @diary.config['WEBNAIL_TIME_OUT'] end if @diary.config['WEBNAIL_BROWSER'] then capture.browser = @diary.config['WEBNAIL_BROWSER'] end # for Windows if @diary.config['WEBNAIL_USE_WS'] then capture.usewinShot = @diary.config['WEBNAIL_USE_WS'] if capture.usewinShot then if @diary.config['WEBNAIL_WIN_SHOT'] then capture.winShot = @diary.config['WEBNAIL_WIN_SHOT'] end if @diary.config['WEBNAIL_WIN_BROWSER'] then capture.winBrowser = @diary.config['WEBNAIL_WIN_BROWSER'] end if @diary.config['WEBNAIL_WIN_CONVERT'] then capture.winConvert = @diary.config['WEBNAIL_WIN_CONVERT'] end end end capture.get_large = true if @diary.config['WEBNAIL_GET_LARGE'] capture.get_large = true if / large/ =~ ap img_str = @diary.date + "_" + url.gsub(%r|.+?tps?://|,"").gsub(/[\W\s]/,"_").gsub(/_+$/,"") get_image = true tn_image , large_image = "","" capture.image_prefix = img_str dmy, get_img_str = capture.imageInfo Dir.entries(webnail_dir).each{|imgfile| if /#{get_img_str}/ =~ imgfile then get_image = false end } if get_image then capture.webnail2 end tn_image , large_image = capture.imageInfo if use_inlineimage imgstr = %Q'image(./webnail/#{tn_image} #{alt.gsub(/\ +/," ")})' else imgstr = %Q'#{alt}' : '>') end escape_url = url if /\?/ =~ url then escape_url = url.split("?").first + "?" + CGI::escapeHTML(url.split("?").last) end if @diary.config['WEBNAIL_WITH_AP'] || ap then if / ap/ =~ ap then ap_banner = %Q' ap:banner="./webnail/#{tn_image}"' ret_str = %Q'#{alt}' elsif / large/ =~ ap && capture.get_large then ret_str = %Q'#{imgstr}#{alt}' if use_inlineimage_ex ret_str = %Q'image(#{escape_url}|./webnail/#{tn_image} #{alt.gsub(/\ +/," ")}|#{alt.gsub(/\ +/," ")})' end else ap_banner = %Q' ap:banner="./webnail/#{tn_image}"' ret_str = %Q'#{alt}' end else ret_str = %Q'#{imgstr}' if use_inlineimage_ex ret_str = %Q'image(#{escape_url}|./webnail/#{tn_image} #{alt.gsub(/\ +/," ")}|#{alt.gsub(/\ +/," ")})' end end ret_str << "" } end end end # 単独で実行する =begin if ARGV.size == 1 and /^\d\d\d\d/ !~ ARGV.first then if /http/ =~ ARGV.first then url = ARGV.first capture = Webnail.new(url) img_str = url.gsub(%r|.+?tp://|,"").gsub(/[\W\s]/,"_").gsub(/_+$/,"") capture.usewinShot = true capture.get_large = true capture.out_dir = Dir.pwd capture.image_prefix = img_str capture.webnail2 else puts "webnail.rb URL sample: http://hoge.foo.bar/" puts " ~~~~~~~" exit 1 end end =end =begin Local Variables: mode: ruby coding: japanese-shift-jis-dos End: =end