@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サーバのタイムアウトは長めに調整しました。