developer's diary

最近はc#のエントリが多いです

mechanizeを使って、Yahooブリーフケースのファイルを一括ダウンロードする。(ちょっと修正)

「もしかしたらバグ」を修正してみました。

もしかしたらwindowsのファイル名に使用できない文字が入ってるからエラーが起きるのかもしれない!
と考え、windowsで使用できない文字( "<>|:*?\/ ) を全角に変換しちゃう仕様に修正してみました。

DLに失敗した方。もしかしたら動くかもしれないです。

報告お待ちしてます」(__)L

class YahooBriefcase

  require 'rubygems'
  require 'mechanize'
  require 'Kconv'
  require 'uri'

  BRIEFCASE_LOGIN_URL = "https://login.yahoo.co.jp/config/login?.src=bc&.done=http%3a//briefcase.yahoo.co.jp/&.intl=jp&.linkdone=http%3a//briefcase.yahoo.co.jp/"
  BRIEFCASE_LOGOUT_URL = "http://login.yahoo.co.jp/config/login?logout=1&.src=bc&.intl=jp&.done=http://briefcase.yahoo.co.jp"
  BRIEFCASE_URL = "http://briefcase.yahoo.co.jp/"

  def initialize(id=nil, password=nil, user_agent='Mechanize')

    @agent = WWW::Mechanize.new
    set_user_agent_alias(user_agent)
    briefcase_login(id,password) if id && password
  end

public

  # @param[in] user_agent ユーザエージェント
  def set_user_agent_alias(user_agent)
    @agent.user_agent_alias = user_agent
  end

  # @param[in] id Yahoo!のID
  # @param[in] password Yahoo!のパスワード
  def briefcase_login(id,password)
    @agent.post(BRIEFCASE_LOGOUT_URL)
    @agent.post(BRIEFCASE_LOGIN_URL, "login" => id, "passwd" => password)
  end


  # @param[in] dir ダウンロード先のディレクトリ
  # @param[in] url ダウンロード元のURL
  def all_get(dir, url=BRIEFCASE_URL)
    FileUtils.mkdir_p(dir)
    briefcase(dir,url,@agent)
  end

private

  def briefcase(name,url,agent)

    #fileが存在するurlの正規表現
    file_regexp = Regexp.new('^http://proxy')
    #ディレクトリのurlの正規表現
    dir_regexp = Regexp.new('&.order=&.view=l&.src=bc&.done=')

    infileArr = Array.new

    #現在の階層に存在するurlを取得
    page = agent.get(url)

    #取得したurlを回す。
    page.links.each do |link|

      #urlがディレクトリの場合
      if link.href =~ dir_regexp

        #ディレクトリの位置をinfileArrに入れる
        dirname = Kconv.tosjis(link.to_s).sub(/\n/,"").sub(/^ */,"")
        infileArr << { dirname => link.href }

        #urlがファイルの場合
      elsif link.href =~ file_regexp

        #ファイルの位置をinfileArrに入れる
        filename = Kconv.tosjis(URI.decode(link.href.to_s.sub(/\n/,"").to_s.sub(/\?.*$/,"").reverse.scan(/^(.*?)\//).to_s.reverse))
        infileArr << { filename => link.href }
      end
    end

    #現在の階層に存在するリンクを回す。
    infileArr.each do |dirhash|
      #リンクに対する名前、urlを取得(1回しか回らない)
      dirhash.each do |name2, url2|

        name2 = name2.sub(/"/,"").sub(/</,"").sub(/>/,"").sub(/\|/,"").sub(/:/,"")
        name2 = name2.sub(/\*/,"").sub(/\?/,"").sub(/\\/,"").sub(/\//,"")

        #urlがディレクトリの場合
        if url2 =~ dir_regexp then

          #ダウンロード先のディレクトリが存在しない場合は作成
          FileUtils.mkdir_p("#{name}/#{name2}")

          #再起呼び出し
          briefcase("#{name}/#{name2}",url2,agent)
          next
        end

        #urlがファイルの場合
        if url2 =~ file_regexp

          #ファイルを取得
          file = agent.get(url2)
          filename = Kconv.tosjis(name2).sub(/\n/,"")
          File.open("#{name}/#{name2}","w+b") do |line|
            line << file.body
          end
  
          #取得したファイル名を出力する。
          puts "#{name}/#{name2}"
        end
      end
    end
  end
end