VOA Special English の Podcast 用 RSS 生成 for Ruby

あけましておめでとうございます。


最近、VOA Special English を聞いているのだが、サイトで提供されている Podcast は複数の記事をまとめて30分にしたてられているため、若干聞きにくい。またサイト上にあるスクリプトとの対応もわかりにくい。
http://www.voanews.com/specialenglish/ から個々の記事を開けば、スクリプトと音声ファイルの両方が取得できるので、ここから Podcast 用の RSS を起こせば、望むものが手に入りそうだ。


と思った瞬間に、きっとどこかの誰かが「それ Plagger で」と言ってそうな気がしたので、"voa plagger" でググってみる。ビンゴ(笑)。

VOA News Special EnglishをトランススクリプトつきでPodcasting
http://d.hatena.ne.jp/mteramoto/20061005/p1

ふむ、やっぱり Plagger ならできそうだ。
だが、使っているレンタルサーバPlagger を入れようとしてすでに一度挫折している(Perlバージョンがあわない……)。
ぜひ Plagger 教には入信したいと思う今日この頃なので、これを機に頑張ってみるのもいいのだが、自分はいかんせんこの手の依存関係のあるインストール話はいつも泥沼に陥りがち。
あれこれ奮闘したあげく、Plagger が動かないだけならまだしも、今まで動いていたものが動かなくなってしまうこともちらほら……


というわけで、Ruby でさっくり書いてみた(ruby1.8.4 で動作確認。1.8.2 以降なら動くかな?)。
筋の良くない「車輪の再発明」(発見とか勉強とか、プロセスに得るものがあまりない)なのでメリットはほとんどないのだが……強いてあげるなら、Ruby と標準ライブラリさえ入っていれば動くことと、「やっぱり Plagger の EntryFullText は強力やなあ」と実感できたことか?


なお、単語数が欲しいなあと思ったので、タイトルに "[371] The New Year Begins With Some Resolutions" という感じで先頭に単語数(適当に数えているので、誤差あり)が入るようにした。
あと、iPod nano の画面はやっぱり小さすぎて、スクリプトを見るにはちょっとつらい。できればスクリプトをもっと手軽にみられるようメールで自分宛に送るようにしたいところ。「それ、Pla(ry


【2007/04/13 追記 ここで紹介しているスクリプトで生成した PodcastRSS英語学習のページ にて配布してみている。「スクリプトなんか見てもしゃーないねん。Podcastのデータが欲しいねん」という方はそちらへどぞ。
なお、おそらく問題ないと思うのだが、万一なんらかの支障が発生した場合は仕様が変わったり無くなったりするかもしれない。念のため。

#!/usr/bin/ruby
# VOA Special English Poscast Generator

HOST = "www.voanews.com"
PATH = "/specialenglish/customCF/RecentStoriesRSS.cfm?keyword=TopStories"

require 'cgi'
require 'date'
require 'net/http'
require 'rexml/document'
require 'uri'

def h(st)
	CGI::escapeHTML(st)
end

dom = Net::HTTP.start(HOST) do |http|
	response = http.get(PATH)
	REXML::Document.new(response.body)
end

puts <<HEAD
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>VOA Special English</title>
<link>http://www.voanews.com/specialenglish/</link>
<description>VOA Special English</description>
<language>en</language>
<pubDate>#{DateTime.now.strftime('%a, %d %b %Y %H:%M:%S %z')}</pubDate>
HEAD

itemlist = dom.elements.to_a('rss/channel/item')
itemlist.each do |item|

	title = item.elements['title'].text
	link = item.elements['link'].text
	uri = URI.parse(link)

	xhtml = Net::HTTP.start(uri.host, uri.port) do |http|
		http.get(uri.path).body
	end
	body = if xhtml =~ /<span class="body">(.+?)<\/span>/mi then $1 else "" end
	mp3 = if xhtml =~ /<a href="(.+?)" class="media-asset"/i then $1 else "" end
	datetext = if xhtml =~ /<span class="datetime">(.+?)<\/span>/ then $1 else "" end
	body = body.gsub(/<.+?>/, '').gsub(/\n\n\n+/, "\n\n").gsub(' ', ' ')
	date = Date.parse(datetext.gsub(/<.+?>/, ''))
	wordcount = body.scan(/\w+/).length

	puts <<ITEM
<item>
<title>[#{wordcount}] #{h title}</title>
<link>#{h link}</link>
<pubDate>#{date.strftime('%a, %d %b %Y %H:%M:%S %z')}</pubDate>
<dc:creator>VOA</dc:creator>
<dc:subject>English</dc:subject><dc:subject>News</dc:subject>
<description><![CDATA[
#{body}
]]></description>
<enclosure url="#{h mp3}" length="" type="audio/mpeg" />
</item>
ITEM

end

puts <<FOOT
</channel>
</rss>
FOOT