サイトから番組表をダウンロードし、必要な部分(局名、番組開始時刻、番組名、番組内容)を取り出す
(get_tvprog.rb)
#!/usr/bin/env ruby require 'nokogiri' require 'open-uri' doc = Nokogiri::HTML(STDIN) #局名を保存する line = [] ch_area = doc.css('#ch_area') ch_area.css('ul').each do |ul| ul.css('li').each do |li| li.css('p').each do |p| #puts "#{p}\n" line.push(p.text) end end end #puts line program = doc.css('#program_area') idx = 0 program.css('ul').each do |ul| puts "<line id=\"#{line[idx]}\">" ul.css('li').each do |li| if( li[:s].to_s.size == 12 ) #番組開始時刻? puts " <time s=\"#{li[:s]}\">" li.css('div.program_text').each do |div| #番組名?番組内容? div.css('p').each do |p| puts " #{p}\n" end end puts " </time>\n" end end puts "</line>\n" idx += 1 end
実行してみる
番組のサイトから、2024年11月3日の神奈川の地デジ番組表をダウンロードし、必要な部分を取り出す
$ curl "https://bangumi.org/epg/td?broad_cast_date=20241103&ggm_group_id=45" | ./get_tvprog.rb
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 478k 100 478k 0 0 429k 0 0:00:01 0:00:01 --:--:-- 430k
<line id="1 NHK総合1..">
<time s="202411030500">
<p class="program_title">ニュース・気象情報</p>
<p class="program_detail"></p>
</time>
<time s="202411030510">
<p class="program_title">大河ドラマ「光る君へ」2分ダイジェスト(41)揺らぎ🈑</p>
<p class="program_detail">三条天皇(木村達成)から悩ましい願いを託される道長(柄本佑)。一方、まひろ(吉高由里子)は、彰子(見上愛)の意向で和歌の会を催すことに。すると招かれざる客が…</p>
</time>
<time s="202411030512">
<p class="program_title">ドラマ10「宙わたる教室」PR🈑</p>
<p class="program_detail">実話に着想を得た感動小説を窪田正孝を主演に迎えてドラマ化した「宙わたる教室」。第4話の振り返りダイジェストと第5話のみどころを2分で紹介。</p>
</time>
<time s="202411030514">
<p class="program_title">SDGsのうた アオ・キイ版 目標17 パートナーシップで目標を達成しよう</p>
<p class="program_detail">「ひろがれ!いろとりどり」は#SDGsを楽しく学んでいく番組シリーズ。「SDGsのうた」ではSDGsの目標を1つずつ、アオとキイの歌とアニメで紹介していくよ!</p>
</time>
...
上記の出力を、excelファイルにワークシートとして追加する
(add_tvprog2xlsx.rb)
#!/usr/bin/env ruby require 'kconv' require 'nokogiri' require 'open-uri' require 'rubyXL' require 'rubyXL/convenience_methods' #48時間制 #24時は翌日の0時、25時は翌日の1時 cnt = Array.new(48) #各時間帯(0時、1時..)ごとの番組数 max = Array.new(48) #各時間ごとの番組数の最大値(セルの位置調整に使用する。NHKEテレが多い。) idx = Array.new(48) #各時間帯の番組名、番組内容の表示位置(セル) adate = ARGV.shift #1日1ファイルとし、番組表はワークシート単位で追加する file = adate.to_s + ".xlsx" if File.exist?(file) workbook = RubyXL::Parser.parse(file) else workbook = RubyXL::Workbook.new workbook.worksheets.delete_at(0) end ARGV.each do |arg| #番組表ファイルを開く f = File.open(arg,"r") doc = Nokogiri::HTML(f, nil, 'utf-8') max.each_index do |i| max[i] = 0 end idx.each_index do |i| idx[i] = 0 end #番組表の読込み doc.css('line').each do |line| print "#{line[:id]}\n" cnt.each_index do |i| cnt[i] = 0 end line.css('time').each do |time| date = time[:s][0,8].to_s hour = time[:s][8,2].to_s puts "date:#{date}\thour:#{hour}\n" if date == adate # x月y日の番組表作成時に、番組開始日がx月y日である cnt[ hour.to_i ] += 1 else # x月y日ではない→翌日と判断する cnt[ hour.to_i + 24 ] += 1 end end cnt.each_index do |i| print "#{i}: #{cnt[i]}\n" end cnt.each_index do |i| if cnt[i] > max[i] max[i] = cnt[i] end end end print "max\n" max.each_index do |i| print "#{i}: #{max[i]}\n" end for i in 1..48 do idx[i] = idx[i-1] + max[i-1] end print "index\n" idx.each_index do |i| print "#{i}: #{idx[i]}\n" end #ワークシートの作成 if workbook["#{arg}"] #ワークシート名が重複する場合は、プログラムを終了する abort "worksheet #{arg} is duplicated!!" else worksheet = workbook.add_worksheet("#{arg}") end view = RubyXL::WorksheetView.new view.pane = RubyXL::Pane.new( top_left_cell: RubyXL::Reference.new(1, 1), y_split: 1, x_split: 1, state: 'frozenSplit', activePane: 'bottomRight' ) views = RubyXL::WorksheetViews.new views << view worksheet.sheet_views = views #一番左のセルに時間(hh00)を書く idx.each_index do |i| worksheet.change_column_vertical_alignment(0, 'top') worksheet.change_column_width(0, 3) worksheet.add_cell(idx[i]+1, 0, i.to_s + "00") worksheet[idx[i]+1][0].change_text_wrap(true) worksheet[idx[i]+1][0].change_font_size(6) end linecnt = 0 doc.css('line').each do |line| pgcnt = 0 print "#{line[:id]}\n" worksheet.change_column_vertical_alignment(linecnt+1, 'top') worksheet.change_column_width(linecnt+1, 12) #局名を書く worksheet.add_cell(0, linecnt+1, line[:id]) worksheet[0][linecnt+1].change_text_wrap(true) worksheet[0][linecnt+1].change_font_size(6) prev_hour = 0 #初期値を仮に0にする line.css('time').each do |time| date = time[:s][0,8] hhmm = time[:s][8,4].to_s hour = hhmm[0,2].to_i if date != adate hour += 24 end if prev_hour != hour pgcnt = idx[hour] end prev_hour = hour program = hhmm + " " time.css('p').each do |p| #puts p.text program += p.text end worksheet.add_cell(pgcnt+1, linecnt+1, program) worksheet[pgcnt+1][linecnt+1].change_text_wrap(true) worksheet[pgcnt+1][linecnt+1].change_font_size(6) #次の番組 pgcnt += 1 end #次の局 linecnt += 1 end end workbook.write(file)
実行してみる
$ ./add_tvprog2xlsx.rb 20241103 20241103.45.temp
1つ目の引数は、日付(yyyymmdd)。番組表のexcelファイル名は、yyyymmdd.xlsxとなる。
2つ目の引数は、yyyymmdd.xlsxに追加する番組表のファイルで、番組表をワークシートで追加する。

実行してみる その2
地上デジ(神奈川)とBSの番組をダウンロードし、20241110.xlsxに追加する。
$ curl "https://bangumi.org/epg/td?broad_cast_date=20241110&ggm_group_id=45" | ./get_tvprog.rb > 20241110.45.temp $ curl "https://bangumi.org/epg/bs?broad_cast_date=20241110" | ./get_tvprog.rb > 20241110.b.temp $ ./add_tvprog2xlsx.rb 20241110 20241110.45.temp 20241110.b.temp

RubyXLで詰まった部分の解消方法と基本動作について
https://qiita.com/arukuishi/items/70014c8040f0409cb35a
ver3.4.0からリソースの無駄を抑えられるように用途に応じたメソッドが呼び出せるようになりました
どちらかと言えば、呼び出さないと使えなくなったのでundefined method Errorが出る場合は確認してください
...