週末はいつも晴れ

社会人3年目の日記です。プログラミングとか旅行とかラーメン。

Naver画像抽出

あるアーティストの壁紙を集めたかったんですが、検索にヒットするのはNaverばかりorz

Naverは一括ダウンロードしにくい仕様になっているので面倒くさいのです!

そこで今後と技術力アップのためにダウンローダRubyで作ることを決意。

紆余曲折を経て、なんとか完成しました(半分以上コピペ)。
こんな僕でも、ライブラリを使えば100行以内に書けてしまうのがRubyの魅力ですよね。

コード
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'open-uri'
require 'nokogiri'

def download(url)

  unless url =~ /^http:\/\/matome\.naver\.jp\/odai\/\d+$/
    print "Requested URL is invalid.\n"
    exit
  end
  
  child_urls = []
  numOfPage=1
  u404s = []
  
  doc = Nokogiri::HTML(open(url))
  ## ページ数取得
  doc.xpath('//div[@class="MdPagination03"]/a').each{|node|
    numOfPage=node.text.to_i
  }

  for i in 1..numOfPage  ## ページ数だけ回す
    puts "Getting links from page #{i} / #{numOfPage}"
    if i!=1
      current_url = url + "?page=#{i}"
      child_urls.clear
      doc = Nokogiri::HTML(open(current_url))
    end
    doc.xpath('//p[@class="mdMTMWidget01ItemImg01View"]/a').each{|node|
      child_urls.push(node["href"])
    }
    
    puts "Downloading #{child_urls.length} pictures .."

    # 画像の数だけthread生成してダウンロード
    Array.new(child_urls.length) do |i|
      Thread.new do
        doc = Nokogiri::HTML(open(child_urls[i]))
        doc.xpath('//p[@class="mdMTMEnd01Img01"]/a').each{|jpg|
          begin
            #
            # 保存方法
            # wgetのほうが早かった。
            
            # save_file(jpg["href"])
            
            sysmte('wget -q -t 3 "#{jpg["href"]}"')
            print "+"
          rescue
            u404s.push(jpg["href"])
          end
        }
      end
    end.each(&:join)
    puts ""
  end

  if u404s.length!=0
    puts "Following URLs were 404 not found"
    u404s.each{|link|
      print "\t", link, "\n"
    }
  end
end

def save_file(url)
  filename = File.basename(url)
  length = filename.length
  if length > 40
    filename = filename[length-40..length-1]
  end
  open(filename, 'wb') do |file|
    open(url) do |data|
      file.write(data.read)
    end
  end
  print "+"
end

def usage
  puts "Usage: ./naver.rb [NAVER_URL]"
end


usage if ARGV.length !=1
download(ARGV[0])