>> 古い記事: Emacs: フェイスをカスタマイズする
<< 新しい記事: Ren'Py: 画像・音声ファイルなどをアーカイブ化する

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Ruby/REXML: CCLedなオーディオコンテンツを紹介するポッドキャストのフィード(RSS2.0)の読み書き

とりあえず作ってはみたものの……といった感じ。 タイトルにあるように「紹介」するためのシンプルなフィードを作るというケースに特化させたもので、 一般的なポッドキャストのフィードとして見た場合間違った使い方になってるかもしれません。


RSS Parser を使おうとしたのですが、次の理由により REXML を使うことにしました。

  • ポッドキャスト用フィードでは RSS 2.0 を使うが、RSS Parser では RSS 2.0 のフィード作成で Dublin Core モジュールが使えないようだった。
  • Creative Commons モジュールが用意されていない。

要件として、以下の情報を個別の item 要素に含めるものとしました。 また、「一次配布元URL」と「ライセンス確認用URL」は一致しない場合もあるのですが、同じものと見なしました。

  • タイトル
  • アーティスト(著作(権)者)名
  • 一次配布元URL
  • ライセンスURL
  • その他コメント・説明
#!/usr/bin/ruby

require "rexml/document"
require "uri"


class REXML::Element
  def add_elem(type, text, attributes=nil)
    elem = REXML::Element.new(type)
    elem.text = text if text
    self.add_element(elem, attributes)
  end
end


def make_rss2(channel_info, tracks)
  rss = REXML::Document.new
  rss << REXML::XMLDecl.new("1.0", "utf-8")

  rss.add_element("rss", 
                  { "version"=>"2.0", 
                    "xmlns:creativeCommons"=>"http://backend.userland.com/creativeCommonsRssModule",
                    "xmlns:dc"=>"http://purl.org/dc/elements/1.1/",
                    "xmlns:atom"=>"http://www.w3.org/2005/Atom"
                  })

  channel = REXML::Element.new("channel")
  channel.add_elem("title", channel_info[:title])
  channel.add_elem("link", channel_info[:link])
  channel.add_elem("description", channel_info[:description])
  rss.elements["rss"].add_element(channel)

  tracks.each {|track|
    item = REXML::Element.new("item")

    item.add_elem("title", "%s (by %s)" % [track[:title], track[:artist]])
    item.add_elem("dc:title", track[:title])

    item.add_elem("dc:creator", track[:artist])
    item.add_elem("author", track[:artist])

    item.add_elem("link", track[:release_url])
    item.add_elem("dc:source", track[:release_url])

    item.add_elem("description", track[:description])

    item.add_elem("guid", track[:audiofile_url])

    item.add_elem("creativeCommons:license", track[:license_url])

    item.add_elem("enclosure", nil,
                     { "url"=>URI.encode(track[:audiofile_url]),
                       "length"=>File.size(track[:audiofile_local_path]),
                       "type"=>"audio/mpeg"
                     })

    rss.elements["rss/channel"].add_element(item)
  }

  return rss
end


################################################################
## データを用意

channel = {
  :title => "フィードのタイトル",
  :link => "http://link.xxx",
  :description => "フィードに関する説明",
}

tracks = []
tracks << {
  :title => "title1 作品1のタイトル",
  :artist => "artist1 作品1のアーティスト",
  :release_url => "http://foolabel.xxx/release/0001/",
  :license_url => "http://creativecommons.org/licenses/by/3.0/",
  :description => "作品1の説明",
  :audiofile_url => "http://audiofile-foo.jp/artist1_title1.mp3",
  :audiofile_local_path => "audiofile/artist1_title1.mp3"
}
tracks << {
  :title => "title2 作品2のタイトル",
  :artist => "artist2 作品2のアーティスト",
  :release_url => "http://barlabel.xxx/release/0002/",
  :license_url => "http://creativecommons.org/licenses/by-nc/3.0/",
  :description => "作品2の説明",
  :audiofile_url => "http://audiofile-bar.jp/artist2_title2.mp3",
  :audiofile_local_path => "audiofile/artist2_title2.mp3"
}


################################################################
## フィードに書き出し

rss_src = make_rss2(channel, tracks).to_s.gsub(/></, ">\n<")
open("sample.xml", "w") {|f|
  f.puts rss_src
}


################################################################
## フィードから読み込み

feed = REXML::Document.new(rss_src)

channel = feed.root.elements["channel"]
puts "title:       " + channel.elements["title"].text
puts "link:        " + channel.elements["link"].text
puts "description: " + channel.elements["description"].text

count = 0
feed.root.elements["channel"].each_element("item") {|item|
  puts "#### item #{count} ####"
  puts "title:          " + item.elements["dc:title"].text
  puts "artist:         " + item.elements["dc:creator"].text
  puts "release_url:    " + item.elements["dc:source"].text
  puts "description:    " + item.elements["description"].text
  puts "license_url:    " + item.elements["creativeCommons:license"].text
  puts "audiofile_url:  " + item.elements["enclosure"].attributes["url"]
  puts "audiofile_type: " + item.elements["enclosure"].attributes["type"]
  count += 1
}

生成されたフィードはこんな感じになります。

<?xml version='1.0' encoding='UTF-8'?>
<rss version='2.0' 
  xmlns:creativeCommons='http://backend.userland.com/creativeCommonsRssModule' 
  xmlns:dc='http://purl.org/dc/elements/1.1/' 
  xmlns:atom='http://www.w3.org/2005/Atom'>

<channel>
<title>フィードのタイトル</title>
<link>http://link.xxx</link>
<description>フィードに関する説明</description>

<item>
<title>title1 作品1のタイトル (by artist1 作品1のアーティスト)</title>
<dc:title>title1 作品1のタイトル</dc:title>
<dc:creator>artist1 作品1のアーティスト</dc:creator>
<link>http://foolabel.xxx/release/0001/</link>
<dc:source>http://foolabel.xxx/release/0001/</dc:source>
<description>作品1の説明</description>
<guid>http://audiofile-foo.jp/artist1_title1.mp3</guid>
<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
<enclosure url='http://audiofile-foo.jp/artist1_title1.mp3' type='audio/mpeg' length='5296'/>
</item>

<item>
<title>title2 作品2のタイトル (by artist2 作品2のアーティスト)</title>
<dc:title>title2 作品2のタイトル</dc:title>
<dc:creator>artist2 作品2のアーティスト</dc:creator>
<link>http://barlabel.xxx/release/0002/</link>
<dc:source>http://barlabel.xxx/release/0002/</dc:source>
<description>作品2の説明</description>
<guid>http://audiofile-bar.jp/artist2_title2.mp3</guid>
<creativeCommons:license>http://creativecommons.org/licenses/by-nc/3.0/</creativeCommons:license>
<enclosure url='http://audiofile-bar.jp/artist2_title2.mp3' type='audio/mpeg' length='10592'/>
</item>

</channel>
</rss>

Creative Commons RSS Module について

  xmlns:creativeCommons='http://backend.userland.com/creativeCommonsRssModule' 

で名前空間を宣言し、その上でライセンス(URL)を指定する。

<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>

基本的にこれだけなので特に難しいことはないです。

サンプル

↓オーディオデータ込みでサンプル作ってみました。
http://dl.getdropbox.com/u/217014/fixed-data/cc-podcast-feed/sample.xml

その他

  • <, & などは REXML 側で勝手にエスケープ、エスケープ解除してくれる。
  • item要素の title, link は必須なのでとりあえず埋めておく。 曲の情報はフィード自体のメタデータとは別にした方がいいような気がするので、 アプリケーション側では dc:title, dc:source を利用する、としてみた。
  • podcatcher によっては dc:creator を見てくれないので RSS に書き出す場合は両方に詰める。RSS から読む場合は dc:creator を読む(ようにした)。
  • pubDate などは Time.rfc822 を使って変換する。

関連記事

参考(外部リンク)

Creative Commons License
This work by sonota is licensed under a Creative Commons Attribution 2.1 JP License.

>> 古い記事: Emacs: フェイスをカスタマイズする
<< 新しい記事: Ren'Py: 画像・音声ファイルなどをアーカイブ化する
** ホームに戻る

コメント

コメントの投稿

管理者にだけ表示を許可する

|
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。