Advertisement
riocampos

gogakuondemand.rb (v3.0)

Jul 31st, 2013
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 5.46 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2. # coding: utf-8
  3.  
  4. # 全講座DLで約20分、約557MB(mp4からmp3への変換はPC能力に依存)
  5.  
  6. require 'nokogiri'
  7. require 'net/https'
  8. require 'fileutils'
  9. require 'kconv'
  10.  
  11. def load_pref
  12.   set_script_dir
  13.   load_pref_file
  14.   load_subjects_file
  15.   set_save_file_dest_dir
  16. end
  17.  
  18. def set_script_dir
  19.   @script_dir = File.expand_path(File.dirname(__FILE__))
  20.   push_dir(@script_dir)
  21. end
  22.  
  23. def load_pref_file
  24.   load './pref.rb'
  25.   @select_subjects_jp = []
  26.   pref.each do |k,v|
  27.     @select_subjects_jp << k if v
  28.   end
  29. end
  30.  
  31. def load_subjects_file
  32.   load './subjects.rb'
  33.   @select_subjects = []
  34.   @subject_urls = subject_urls
  35.   @subjects_jp  = subjects_jp
  36.   @select_subjects_jp.each do |sub_jp|
  37.     @select_subjects << @subjects_jp[sub_jp]
  38.   end
  39. end
  40.  
  41. def set_save_file_dest_dir
  42.   working_dir = save_file_dest_dir ?
  43.                 File.expand_path(File.path(save_file_dest_dir)) :
  44.                 File.expand_path(File.dirname(__FILE__))
  45.   Dir.mkdir(working_dir) unless File.directory?(working_dir)
  46.   push_dir(working_dir)
  47. end
  48.  
  49. def is_win?
  50.   RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|cygwin|bccwin/ ? true : false
  51. end
  52.  
  53. def print_download_subjects
  54.   download_subjects = @select_subjects_jp * "、"
  55.   print "ダウンロードする語学講座:#{download_subjects}\n\n"
  56. end
  57.  
  58. def https_body(url)
  59.   uri = URI.parse(url)
  60.   https = Net::HTTP.new(uri.host, uri.port)
  61.   https.use_ssl = true
  62.   https.ssl_version = :TLSv1
  63.   https.verify_mode = OpenSSL::SSL::VERIFY_NONE
  64.   if uri.query
  65.     https.get(uri.path + '?' + uri.query).body
  66.   else
  67.     https.get(uri.path).body
  68.   end
  69. end
  70.  
  71. def get_source_urls
  72.   data_hash ={}
  73.   @select_subjects.each do |sub|
  74.     url = "https://cgi2.nhk.or.jp/gogaku/#{@subject_urls[sub]}/listdataflv.xml"
  75.     doc = Nokogiri.XML(https_body(url))
  76.     data_array = doc.xpath("/musicdata/music")
  77.     date = data_array.map { |d| d["hdate"].scan(/(\d+)(\d+)/)} \
  78.           .map{ |dt| "#{record_year(dt[0][0].to_i)}_%02d_%02d" % dt.flatten}
  79.     data_hash[sub] = {kouza: data_array[0].values[2]}
  80.     data_array.each_with_index do |d, i|
  81.       data_hash[sub][{date: date[i]}] = data_array[i].values[4]
  82.     end
  83.   end
  84.   data_hash
  85. end
  86.  
  87. def record_year(record_month)
  88.   now = Time.now
  89.   this_month = now.month
  90.   this_year = now.year
  91.   @record_year = this_month - record_month < 0 ? this_year - 1 : this_year
  92. end
  93.  
  94. def prepare_download_each_subject(key, value)
  95.   @subject = value[:kouza]
  96.   puts "講座名:#{@subject}"
  97.   subject_dir = File.join(current_dir, key.to_s + "/")
  98.   Dir.mkdir(subject_dir) unless File.directory?(subject_dir)
  99.   subject_dir
  100. end
  101.  
  102. def each_date_process(key, value)
  103.   value.each do |k, v|
  104.     next if k == :kouza
  105.     @metadata = {}
  106.     date = k[:date]
  107.     @metadata[:subject]   = @subject
  108.     @metadata[:title]     = "#{key}_#{date}"
  109.     @metadata[:title_jp]  = "#{@subject}_#{date}"
  110.     @metadata[:genre]     = "Speech"
  111.     @metadata[:create]    = "NHK"
  112.     @metadata[:year]      = @record_year.to_s
  113.     puts "日付:#{date}"
  114.     download_ondemand_file(v)
  115.   end
  116. end
  117.  
  118. def download_ondemand_file(subject_code)
  119.   master_m3u8 = "https://nhk-vh.akamaihd.net/i/gogaku-stream/mp4/#{subject_code}/master.m3u8"
  120.   title_path_jp = is_win? ?
  121.                   File.join(current_dir, @metadata[:title_jp].tosjis) :
  122.                   File.join(current_dir, @metadata[:title_jp])
  123.   if is_win?
  124.     command_ffmpeg = %Q[ffmpeg -y -i #{master_m3u8} -ab 64k -metadata album="#{@metadata[:subject].tosjis}" -metadata title="#{@metadata[:title_jp].tosjis}" -metadata genre="#{@metadata[:genre]}" -metadata artist="#{@metadata[:create]}" -metadata date="#{@metadata[:year]}" -id3v2_version 3 #{title_path_jp}.mp3 > nul 2>&1]
  125.     IO.popen(command_ffmpeg){ print "ダウンロード中...\n" }
  126.   else
  127.     command_ffmpeg = %Q[ffmpeg -y -i #{master_m3u8} -ab 64k -metadata album="#{@metadata[:subject]}" -metadata title="#{@metadata[:title_jp]}" -metadata genre="#{@metadata[:genre]}" -metadata artist="#{@metadata[:create]}" -metadata date="#{@metadata[:year]}" -id3v2_version 3 #{title_path_jp}.mp3 2>&1]
  128.     print "ダウンロード中...\n"
  129.     IO.popen(command_ffmpeg) do |pipe|
  130.       duration = nil
  131.       progress = 0
  132.       pipe.each("r") do |line|
  133.         if line =~ /: (\d{2}):(\d{2}):(\d{2}).(\d{2}),/
  134.           duration = (($1.to_i * 360000 + $2.to_i * 6000 + $3.to_i * 100 + $4.to_i) / 100.0).round
  135.         end
  136.         if line =~ /time=(\d{2}):(\d{2}):(\d{2}).(\d{2})/
  137.           progress = (($1.to_i * 360000 + $2.to_i * 6000 + $3.to_i * 100 + $4.to_i) / 100.0).round
  138.           progress = duration if duration && progress > duration
  139.         end
  140.         if duration
  141.           progress_bar(progress, duration, "秒")
  142.         end
  143.       end
  144.       print "\n"
  145.     end
  146.   end
  147. end
  148.  
  149. def progress_bar(progress, max, unit)
  150.   max_digits = max.to_s.size
  151.   print "\r" + "[#{'%-50s' % ('*' * (progress.to_f / max * 50).to_i)}] #{'%*d' % [max_digits, progress]} / #{max} #{unit}"
  152. end
  153.  
  154. def current_dir
  155.   @pwd
  156. end
  157.  
  158. def push_dir(dir)
  159.   @pwds ||= []
  160.   @pwds.push(dir)
  161.   @pwd = @pwds.last
  162.   Dir::chdir(@pwd)
  163.   @pwd
  164. end
  165.  
  166. def pop_dir
  167.   @pwds.pop
  168.   @pwd = @pwds.last
  169.   Dir::chdir(@pwd)
  170.   @pwd
  171. end
  172.  
  173. def gogaku_on_demand
  174.   load_pref
  175.   print_download_subjects
  176.   data_hash = get_source_urls
  177.   data_hash.each do |key, value|
  178.     subject_dir = prepare_download_each_subject(key, value)
  179.     push_dir(subject_dir)
  180.     each_date_process(key, value)
  181.     pop_dir
  182.   end
  183.   puts "作業終了"
  184. end
  185.  
  186. gogaku_on_demand
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement