PowerShell で RSS 取得

思い立ったが吉日とはよく言ったもので、以前から、 PowerShell で RSS の取得とか書きたいな、と思いつつだらだらしていたら先を越された。
PowerShellで外部のRSSフィードを取得する − @IT

せっかくなので勉強も兼ねて、参考にしつつも自分なりのやり方でやってみよう。自分としては方針は以下の通り。
・ps1 ファイルにするのではなくプロンプト上でやりたい。思い立ったときにサクッと動かしたい。そのためにはプロンプト上で対話的なのが好み。
・そのためにもとにかく短いコードにしたい。結果を求めるまでに最小の時間でたどり着きたい。
・楽をしたい。PowerShellエイリアスやタブ補完などを有効に活用しよう。

プロンプト上での対話的、試行錯誤的なやりとりというのが、PowerShell の魅力のひとつだと思っているのでそのライブ感のようなものを大事にしたい。


では早速始めましょうー。


指定した URL の情報を取得するには、System.Net 名前空間の WebClient クラスを使います。

$wc = New-Object System.Net.WebClient

New-O まで入力して、Tab を押すと、New-Object と補完してくれます。


次に URL を指定して情報取得。 @IT の記事では DownloadData メソッドを使っていますが、これだとバイナリとして返ってきて後処理が必要なので、String 型を返す DownloadString メソッドを使います。

$rss = $wc.DownloadString("http://d.hatena.ne.jp/p-nix/rss2")

$wc.d と入力して Tab を押すと補完されます。d で始まるメソッドはいくつかあるので DownloadString が出るまで何度も Tab を押しましょう。行き過ぎたら Shift + Tab で戻れます。

さて、これで rss が取得できたのではないでしょうか。見てみましょう。

$rss

<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0"
        xmlns:dc="http://purl.org/dc/elements/1.1/"
        xmlns:content="http://purl.org/rss/1.0/modules/content/"
        xml:lang="ja">
        <channel>
                <title>蟄ヲ縺ウ縲√◎縺励※閠・∴繧・/title>
                <link>http://d.hatena.ne.jp/p-nix/</link>
                <description>蟄ヲ縺ウ縲√◎縺励※閠・∴繧・/description>
                <dc:creator>p-nix</dc:creator>




                <item>
                        <title>[silverlight] 繧「繝ォ繝舌Β菴懈・縲∝・譛峨し繝シ繝薙せ TORIPOTO 縺ョ菴ソ縺・婿</title>
                        <link>http://d.hatena.ne.jp/p-nix/20080320/p3</link>

・・・

ガーン、文字化けしている。そう、この RSSエンコーディングUTF-8 なのです。単純に DownloadString ではダメなようです。

WebClient クラスに Encoding プロパティがあります。ここで設定できそうな予感。ちなみに現在のエンコーディングは何になっているのかな。

$wc.Encoding

どうやら Shift-JIS みたいです。そりゃ文字化けするよな。UTF-8 に変更しましょう。

$wc.Encoding = [System.Text.Encoding]::UTF8

再び DownloadString を実行。上矢印キー何度か押して先ほど実行したコマンドを呼び出して再度実行。

$rss = $wc.DownloadString("http://d.hatena.ne.jp/p-nix/rss2")

さあ、今度はどうかな。

$rss

<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0"
        xmlns:dc="http://purl.org/dc/elements/1.1/"
        xmlns:content="http://purl.org/rss/1.0/modules/content/"
        xml:lang="ja">
        <channel>
                <title>学び、そして考える</title>
                <link>http://d.hatena.ne.jp/p-nix/</link>
                <description>学び、そして考える</description>
                <dc:creator>p-nix</dc:creator>




                <item>
                        <title>[silverlight] アルバム作成、共有サービス TORIPOTO の使い方</title>
                        <link>http://d.hatena.ne.jp/p-nix/20080320/p3</link>

・・・

やったー、文字化け解消。


しかし、これでは rss の内容がズラーッと大量に表示されて見づらいことこの上ない。せめてタイトルの一覧など絞って表示したい。

RSSXML形式なので、.NET FrameworkXML 系のクラスをフル活用することで必要な情報のみ取得することができます。かといってあまり複雑なことをしてプログラムが長くなると方針に反するのでその辺要注意。


まず $rssXML型に変換。これは @ITと同じやり方で。これ以上短くはできないと思うので。

$feed = [xml]$rss


各エントリは、 の中にある ごとに格納されています。それを考慮に入れて以下のようにやってみる。

$feed.rss.channel.item

title       : [silverlight] アルバム作成、共有サービス TORIPOTO の使い方
link        : http://d.hatena.ne.jp/p-nix/20080320/p3
description : description
creator     : p-nix
pubDate     : Wed, 19 Mar 2008 15:00:00 GMT
category    : silverlight
enclosure   : enclosure

title       : [windows][vista] 言語パックのアンインストールは果てなく続く
link        : http://d.hatena.ne.jp/p-nix/20080320/p2
description : description
creator     : p-nix
pubDate     : Wed, 19 Mar 2008 15:00:00 GMT
category    : {windows, vista}

・・・

お、いい感じ。もう一息。title だけに絞り込みましょう。

$feed.rss.channel.item | %{$_.title}

[silverlight] アルバム作成、共有サービス TORIPOTO の使い方
[windows][vista] 言語パックのアンインストールは果てなく続く
[windows][vista] 言語パックてんこ盛りのマシンに Vista SP1
[本][ミステリ]グラン・ギニョール城
[雑感][システム開発]
[.net][ツール] .NET のソースコードを解析、NDepend ファーストレビュー
[adobe][air] Adobe AIR 1.0、Flex 3 日本語版リリース

目的達成。おつかれさまでした。
% というのは、for-each-object のエイリアス。item が複数あるのでその個数分ループします。現在の item の値は $_ という変数に格納されています。そこで title だけ抽出するというわけです。


まとめると、

$wc = New-Object System.Net.WebClient
$wc.Encoding = [System.Text.Encoding]::UTF8
$rss = $wc.DownloadString("http://d.hatena.ne.jp/p-nix/rss2")
$feed = [xml]$rss
$feed.rss.channel.item | % {$_.title}

となります。

というわけで意外にお手軽楽ちんな PowerShell。積極的に活用していきたいです。