「VOA Special EnglishのPodcast用RSS生成 for Ruby」を勝手に添削 (できるほどRubyistではないのに)
うっかりTOEICを申し込んでしまったので、ちょっと本気で英語勉強しよ!と思っているbonlifeです。英語に耳を慣らすためにPodcastの購読を増やすことを検討。VOAあたりが良いってウワサを聞いたことがあったので調べてみると、何やら便利そうなものを公開してる人発見です!
- id:n_shuyo:20070101:voa
ほうほう、と思ってリンク先のリンク先のRSSをiTunesに登録すると、descriptionが出てくるヤツと出てこないヤツがあってガッカリ…。仕方なくあんまり得意じゃないRubyのコードを見てみると、以下のような箇所が…。
body = if xhtml =~ /<span class="body">(.+?)<\/span>/mi then $1 else "" end
うわぁん、なぜか最短一致使ってる!これだと関係ないspanタグが途中にあると、そこで終わってしまう罠。
思い立ったが吉日生活、ということで頑張ってRubyでコード書き直してみました。Rubyのコードとして根本的に色々間違ってそうな予感です。 (「Hpricot で link タグが勝手に空要素になる - kaeruspoon」の現象でハマったのは秘密です。)
- VOARSSGenerator.rb
#!/usr/bin/ruby # VOA Special English Poscast Generator require 'cgi' require 'date' require 'hpricot' require 'open-uri' class VOARSSGenerator @@TARGET_URL = "http://www.voanews.com/specialenglish/customCF/RecentStoriesRSS.cfm?keyword=TopStories" def generate_voa_rss generate_rss_header xml = Hpricot.XML(open(@@TARGET_URL)) (xml/"rss/channel/item").each do |item| title = (item/"title").text link = (item/"link").text mp3, wordcount, date, description = parse_each_link(link) generate_item_xml(title, link, mp3, wordcount, date, description) end generate_rss_footer end def generate_rss_header 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 end def generate_rss_footer puts <<FOOT </channel> </rss> FOOT end def parse_each_link(link) doc = Hpricot(open(link)) ((doc/"span.body/")./".imagecaption").remove description = (doc/"span.body").first.inner_html.gsub(/\n+/," ").gsub(/<br(?: ?\/)?>/,"\n").gsub(/<\/p>/,"\n\n").gsub(/ /," ").gsub(/<\/?[^>]*>/, " ").gsub(/ +/," ").gsub(/^ /,"").sub(/^\s+/,"").sub(/\s+\Z/m,"") date = Date.parse((doc/"span.datetime/em").first.inner_html) mp3 = ((doc/"a.media-asset").first)[:href] wordcount = description.scan(/\w+/).length return mp3, wordcount, date, description end def h(st) CGI::escapeHTML(st) end def generate_item_xml(title, link, mp3, wordcount, date, description) 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[ #{description} ]]></description> <enclosure url="#{h mp3}" length="" type="audio/mpeg" /> </item> ITEM end end v = VOARSSGenerator.new v.generate_voa_rss
parse_each_link の description まわりの処理がおそろしく力技。しかも微妙。関数に値を色々と渡してるところもダサいけど、まぁ良いか。後、CDATAに入れるデータがどうなってれば良いのか、とかXMLの基本が分かってないんですよね。(そのあたりはまた後で勉強しよっと。) id:n_shuyoさんが部分的に修正してくれると嬉しいなぁ、とかなんとか。