harukazepc’s blog

インターネッツとAndroidなどが大好きです。あとは日々のことなど。

rubyでインターネット上の画像一覧を取得→zip化するCGI

@niftyTimeLineの終了に伴い、登録したtimelineの画像を全部回収する、というものを作ってみたのでコードをさらしてみる。

今回はTimeLineのAPIですが、画像一覧のスクレイピング処理さえ変えれば、いかようにも使えますかね。
zip化については、今回は zipruby を使いました。かなり楽ちん。

require 'cgi'
require 'open-uri'
require 'rexml/document'
require 'rubygems'
require 'zipruby'
require "tmpdir"

include REXML

cgi = CGI.new

user_id = cgi.params['user_id'][0] || exit
timeline_key = cgi.params['timeline_key'][0] || exit

api_url0 = 'http://api.timeline.nifty.com/api/v1/timelines/search?hits=100&'
api_url1 = 'http://api.timeline.nifty.com/api/v1/articles/search?hits=1000&'
api_url2 = 'http://api.timeline.nifty.com/api/v1/articles/image/'

# 画像の処理をするパスを「CGIの実行パス/tmpdir」に設定
current_path = Dir.pwd+"/tmpdir"

# 特定ユーザのタイムライン一覧の取得
response0 = open(api_url0+'owner='+user_id+'&timeline_key='+timeline_key)
response0_xml = Document.new(response0.read)

# 一時画像保管ディレクトリの作成
dir_path = Dir.mktmpdir(nil, current_path) 
zip_targets = []

response0_xml.elements.each("response/result/timelines/timeline/id") { |timeline_id|
    timeline_dir_path = dir_path+"/"+timeline_id.text
    Dir.mkdir(timeline_dir_path)
 
    response1 = open(api_url1+'timeline_id='+timeline_id.text+'&timeline_key='+timeline_key) 
    response1_xml = Document.new(response1.read)
    response1_xml.elements.each("response/result/articles/article") { |article|
        article_id = article.text("id")
        next if (image_api_url = article.text("image")) == nil 
        response2 = open(image_api_url+"?timeline_key="+timeline_key)
      
        # 拡張子判定、、、すいません手抜きです
        extention = 'jpg' 
        extention = 'jpg' if response2.content_type == 'image/jpeg'
        extention = 'gif' if response2.content_type == 'image/gif'
        extention = 'png' if response2.content_type == 'image/png'
        
        filename = timeline_dir_path+"/img_t"+timeline_id.text+"_a"+article_id+'.'+extention
        
        img_file = File.open(filename,'w')
        img_file.puts(response2.read)
        img_file.close
    }
    # zip化の対象リストに加える
    zip_targets.push(timeline_id.text)
}

# サーバ上でzipに固める
zip_file = dir_path+".zip"
Zip::Archive.open(zip_file,Zip::CREATE) { |arc|
    zip_targets.each{|d|
       arc.add_dir(d)
       timeline_dir_path = dir_path+"/"+d
       Dir.glob(timeline_dir_path+"/*").each { |f|
          zip_entry_name = /\/(\d+\/.+)$/.match(f).to_a[1]
          arc.add_file(zip_entry_name,f)
       }
    }
}

# 固めたzipを返却
cgi.out({
	"type" => "application/zip",
	"Content-Disposition" => "attachment; filename=\"TimeLineImages_"+user_id+".zip"+"\""
	}) { File.read(zip_file) }

完成品はこちら。
TimeLine画像回収さん

CGIで画像取得→zip化→返却までやってるので、正直かなり強引。
本当はデーモン化して処理予約だけ受付→裏で処理完了後にメール等で通知、がいいんでしょうが、、、まぁそんなに利用されるものじゃないので。
ただ、さすがにwebサーバのタイムアウトは長めに調整しました。

© harukazepc️