Help us understand the problem. What is going on with this article?

<音泉>の新着をprograms.xml からXSLTで抽出してダウンロードする

More than 1 year has passed since last update.

音泉といえば TBS ラジオの番組かと思っていたら、インターネットラジオ配信サイトのことらしい。
<音泉>のコンテンツを自動録音(保存)する。」によると、その音泉の公開コンテンツの一覧が、http://www.onsen.ag/app/programs.xml で公開されているという。

この XML データを眺めていると program の category に new という直があって、この直が 1 のとき、新着を表しているらしい。

XML からデータを抽出するなら XPATH で条件を指定して、いっそのこと XSLT 処理すればよいのでは……、ということで、XSLT の手習いとしてテンプレートを書いてみた。

  • データは xsl:value-of で出力できる。

  • 抽出条件は以下の通り。
    xsl:if を使えば、条件にマッチしたときだけ処理を行うことができる。

    • is_app0 のときは、*_url にはデータが入っていない。
    • category/new1 の時だけデータを出力したい。
  • up_date の時刻部分は不要で、日付部分だけ取り出したい。
    select のところは式がかける。substring 関数を使えばよい。

  • そのままでは値が空白区切りで出力される。
    あとでシェルスクリプトで処理するため、区切りが空白では、値に空白が入ったときに扱いにくい。
    改行を区切りとするには、xsl:text で改行を生成すればよい。

programtitle, up_date の日付部分、データの URL を順に出力し、レコードの区切りを // としている。

programs.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="text" encoding="utf-8"/>

  <xsl:template match="/programs">
    <xsl:apply-templates select="program"/>
  </xsl:template> 

  <xsl:template match="program">
    <xsl:variable name="is_app" select="is_app"/>
    <xsl:variable name="is_new" select="category/new"/>
    <xsl:variable name="movie_url" select="movie_url"/>
    <xsl:variable name="iphone_url" select="iphone_url"/>
    <xsl:variable name="android_url" select="android_url"/>
    <xsl:if test="is_app='1' and is_new='1'">
      <xsl:value-of select="title"/>
      <xsl:text>
</xsl:text>
      <xsl:value-of select="substring(up_date, 0, 11)"/> 
      <xsl:text>
</xsl:text>
      <xsl:value-of select="movie_url"/> 
      <xsl:if test="iphone_url != movie_url">
        <xsl:text>
</xsl:text>
        <xsl:value-of select="iphone_url"/> 
      </xsl:if>
      <xsl:if test="android_url != iphone_url">
        <xsl:text>
</xsl:text>
        <xsl:value-of select="android_url"/> 
      </xsl:if>
      <xsl:text>
//
</xsl:text>
    </xsl:if>
  </xsl:template> 

</xsl:stylesheet>

このテンプレートを使って programs.xml を xsltproc で処理する。
実行結果は以下のようになる。

$ xsltproc programs.xslt programs.xml
千本木彩花・和多田美咲・赤尾ひかるのようこそ!グリーンハーベスト
2017-01-14
http://onsen.b-ch.com/radio/youkoso170114Xi4p.mp4
//
幼女戦記 ラジオの悪魔
2017-01-14
http://onsen.b-ch.com/radio/youjo170114Xi4p.mp3
//

ここまで来れば、あとはシェルスクリプトでダウンロード処理が書ける。

get-programs.sh
#!/bin/sh

ONSEN_DIR=onsen
case "$0" in
    ./*) SCRIPTNAME="$(pwd)/${0#./}";;
    /*)  SCRIPTNAME="$0";;
    *)   SCRIPTNAME="$(pwd)/$0";;
esac
SCRIPTDIR="${SCRIPTNAME%/*}"

stylesheet=$SCRIPTDIR/programs.xslt

if which aria2c >/dev/null; then
fetch()
{
    aria2c -x4 "$@"
}
else
fetch()
{
    wget "$@"
}
fi

[ -d "$ONSEN_DIR" ] || mkdir -p "$ONSEN_DIR"
cd "$ONSEN_DIR"
trap "mv programs.xml programs.xml.old" EXIT HUP INT
fetch -q http://www.onsen.ag/app/programs.xml
[ $? -eq 0 ] || { echo "programs.xml: get failed"; exit 1; }
xsltproc "$stylesheet" programs.xml |
while read program; do
  read date
  mkdir -p "$program/$date"
  while read url; do
    [ "$url" = "//" ] && break
    filename="$program/$date/${url##*/}"
    [ -f "$filename" ] || fetch -q -o "$filename" "$url"
  done
done

get-programs.sh と programs.xslt を同じディレクトリに配置して起動すれば、ONSEN_DIR で指定したディレクトリに、タイトル/公開日付 でサブディレクトリを作成し、そこにファイルをダウンロードする。
すでにファイルがあるときは、二重にダウンロードはしない。

aria2c は、複数のセッションを使って高速にダウンロードができる軽量ダウンローダーである。
aria2c が存在しないときは wget を使うようにシェル関数 fetch を定義している。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away