OverView
- 元ネタ:いかにしておっぱい画像をダウンロードするか〜2012 をRubyで書いた
- crawlerを作ってみたい
- Rubyなら手軽にできるかもしれない
- 元ネタサイトの作成時と2013/7現在のBingサービスが変わっており
元ネタそのままでは動かないっぽい おっぱい
環境
Rubyが動作する環境であること。
環境構築手順は後日まとめる(つもり)
準備
gemインストール
JSON/SSL/paralelあたりを使うのでgem installしておく。
gem install json gem install ssl gem install parallel
bing search APIのサインアップ
ここにアクセスしてbing search APIを利用できるようにする。
この記事を書いている時のサービスだとサインアップすると5000リクエスト/月が無料で使えた。
うまく登録できると以下の画面で「プライマリアカウントキー」が取得できるのでメモしておく
ソースコード
元ネタから方針を継承して解説しすぎるよりもコードを見てもらう方式で。
ずいぶんと適当なソースになってしまったが、ご愛嬌。
bingがSSLになったことへの対応や、コマンド引数で検索ワードを受けるなど
ちょっとアレンジしてます。
ソース上のAPP_IDに上述のプライマリアカウントキーを。
# coding:UTF-8 require 'rubygems' require 'open-uri' require 'json' require 'digest/md5' require 'uri' require 'kconv' require 'openssl' require 'parallel' #-------------------------------------- # define #-------------------------------------- ## SSL check off module OpenSSL module SSL remove_const :VERIFY_PEER end end OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE #-------------------------------------- # define #-------------------------------------- $loop_count = 0 $dl_count = 0 $params = {} $subParams = {} #-------------------------------------- # define #-------------------------------------- APP_ID = '*******************************' ## https://ssl.bing.com/webmaster/developers/appids.aspx API_URI = 'https://api.datamarket.azure.com/Bing/Search/Image' ## Web/Image/Video/Newsがある OUT_DIR = './data' #-------------------------------------- # init #-------------------------------------- def init ## making save directory Dir.mkdir OUT_DIR unless File.exists? OUT_DIR puts "save to ==>#{File.expand_path(OUT_DIR)}" $subParams = { :Adult => '%27off%27', :Query => '%27' + URI.encode(ARGV[0].toutf8) + '%27' } end #-------------------------------------- # main #-------------------------------------- def main loop do if $dl_count >= 1000 or $loop_count >= 100 then puts "DownLoad End---------" finish end $params = { :format => 'json', :top => 50, # max count per request(max 50) :skip => $loop_count * 50 # cursor } url = API_URI + '?' + $params.map{|k,v| "$#{k.to_s}=#{v.to_s}"}.join('&')+ '&' + $subParams.map{|k,v| "#{k.to_s}=#{v.to_s}"}.join('&') puts "==>Request URL is #{url}" certs = [APP_ID, APP_ID] data = JSON.parse open(url, {:http_basic_authentication => certs}).read.toutf8 if data['d']['results'].size == 0 then puts "DownLoad End(Find No More Data)---------" finish end ## Windows not support parallel if RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|cygwin|bccwin/ downloadTarget(data) else downloadTargetParallel(data) end $loop_count += 1 end end #-------------------------------------- # finish #-------------------------------------- def finish exit end #-------------------------------------- # downloadTarget #-------------------------------------- def downloadTarget(data) ## pop from ResponseData data['d']['results'].each do |entry| next unless entry['MediaUrl'] =~ /\.jpe?g$/i ## entry['Width']とかentry['Height'] entry['FileSize'] なんかも使えそう ## when same file exists skip fname = Digest::MD5.hexdigest(entry['MediaUrl'])+'.jpg' fpath = "#{OUT_DIR}/#{fname}" if File.exists? fpath then puts "---already downloaded #{entry['MediaUrl']}" next end ## Image Download $dl_count += 1 puts "#{$dl_count} : Download... #{entry['MediaUrl']}" img = open(URI.encode entry['MediaUrl']) rescue next img.close next unless img.content_type =~ /^image\/.+/i img.path rescue next next if img.path.to_s.size < 1 File.rename(img.path, fpath) end end #-------------------------------------- # downloadTargetParallel #-------------------------------------- def downloadTargetParallel(data) ## pop from ResponseData Parallel.each(data['d']['results'], :in_thread => 10) do |entry| next unless entry['MediaUrl'] =~ /\.jpe?g$/i ## entry['Width']とかentry['Height'] entry['FileSize'] なんかも使えそう ## when same file exists skip fname = Digest::MD5.hexdigest(entry['MediaUrl'])+'.jpg' fpath = "#{OUT_DIR}/#{fname}" if File.exists? fpath then puts "---already downloaded #{entry['MediaUrl']}" next end ## Image Download $dl_count += 1 puts "#{$dl_count} : Download... #{entry['MediaUrl']}" img = open(URI.encode entry['MediaUrl']) rescue next img.close next unless img.content_type =~ /^image\/.+/i img.path rescue next next if img.path.to_s.size < 1 File.rename(img.path, fpath) end end #-------------------------------------- # handler #-------------------------------------- init main finish
いくつかのキーワードで実行したところ、あっちゅーまに5000ファイルくらいダウンロードしてました。
おためしあれ。