元ネタ:いかにしておっぱい画像をダウンロードするか〜2012 – ゆーすけべー日記


昔、yusukebeさんとは大学で同じ研究室だった。
俺がまともにプログラムを書けるようになったのは、研究室に入った時に新入生向けのyusukebeサブゼミに入って、Flashで実装されたRSSリーダーのソースコードを見せてもらったあたりがきっかけだった気がする。

俺も高校生が(Rubyで)プログラミングをはじめるきっかけになりたいので、Ruby版を作ってみました。
Rubyもこういうwebクローラーを作るのに向いている言語だし、最近のMacなんかには最初からインストールされているので試してみると良いよ。


まずjson gemをインストールする。

sudo gem install json


oppai.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'open-uri'
require 'json'
require 'digest/md5'
require 'uri'
require 'kconv'

APP_ID = '' ## https://ssl.bing.com/webmaster/developers/appids.aspx から取得
API_URI = 'http://api.bing.net/json.aspx'

out_dir = './data'
Dir.mkdir out_dir unless File.exists? out_dir

page_count = 0
dl_count = 0

loop do
params = {
:AppId => APP_ID,
:Version => 2.2,
:Market => 'ja-JP',
:Sources => 'Image',
'Image.Count' => 50,
'Image.Offset' => page_count * 50,
:Adult => 'off',
:Query => 'おっぱい'
}

url = API_URI + '?' + params.map{|k,v| "#{URI.encode k.to_s}=#{URI.encode v.to_s}"}.join('&')
data = JSON.parse open(url).read.toutf8

data['SearchResponse']['Image']['Results'].each do |entry|
next unless entry['MediaUrl'] =~ /\.jpe?g$/i
dl_count += 1
fname = Digest::MD5.hexdigest(entry['MediaUrl'])+'.jpg'
fpath = "#{out_dir}/#{fname}"
next if File.exists? fpath

puts "#{dl_count} : Download... #{entry['MediaUrl']}"
img = open(URI.encode entry['MediaUrl']) rescue next
img.close
next unless img.content_type =~ /^image\/.+/i
next if img.path.to_s.size < 1
File.rename(img.path, fpath)
end
page_count += 1
end



並列ダウンロード版。parallelを使って10並列ダウンロードする。

gem install parallel


oppai_paralle.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'open-uri'
require 'json'
require 'digest/md5'
require 'uri'
require 'kconv'
require 'parallel'

APP_ID = '' ## https://ssl.bing.com/webmaster/developers/appids.aspx から取得
API_URI = 'http://api.bing.net/json.aspx'

out_dir = './data'
Dir.mkdir out_dir unless File.exists? out_dir

page_count = 0
dl_count = 0

loop do
params = {
:AppId => APP_ID,
:Version => 2.2,
:Market => 'ja-JP',
:Sources => 'Image',
'Image.Count' => 50,
'Image.Offset' => page_count * 50,
:Adult => 'off',
:Query => 'おっぱい'
}

url = API_URI + '?' + params.map{|k,v| "#{URI.encode k.to_s}=#{URI.encode v.to_s}"}.join('&')
data = JSON.parse open(url).read.toutf8

Parallel.each(data['SearchResponse']['Image']['Results'], :in_threads => 10) do |entry|
next unless entry['MediaUrl'] =~ /\.jpe?g$/i
dl_count += 1
fname = Digest::MD5.hexdigest(entry['MediaUrl'])+'.jpg'
fpath = "#{out_dir}/#{fname}"
next if File.exists? fpath

puts "#{dl_count} : Download... #{entry['MediaUrl']}"
img = open(URI.encode entry['MediaUrl']) rescue next
img.close
next unless img.content_type =~ /^image\/.+/i
next if img.path.to_s.size < 1
File.rename(img.path, fpath)
end
page_count += 1
end