Daily Archives: 2013年6月23日

RSSリーダーを作ってみる

ブログやニュースなどの更新情報を配信するために用いられるRSS
これを利用して複数のサイトの情報を取得表示しているのがアンテナサイトです。
今回ふと思い立ってこのアンテナサイトを作ることにしたので数回に分けて作成までの道のりをつらつらとつづって行こうと思います。
まずはRSSを解析する仕組みが必要なのですがググって見つかるソースは拡張モジュールのcurlを利用しているものばかり
基本的に拡張モジュールは使いたくないので自力で作ってみることにした。

・rssLoader.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<?php
 
require_once __DIR__."/channelBean.php";
require_once __DIR__."/itemBean.php";
require_once __DIR__."/rssException.php";
require_once __DIR__."/lib/httpConnecter.php";
require_once __DIR__."/lib/xmlLoader.php";
 
class rssLoader {
 
    const VERSION_1 = 1;
    const VERSION_2 = 2;
 
    const VERSION_ALL = 0;
 
    public function __construct() {
    }
 
    public function __destruct() {
    }
 
    /**
     * RSSを読み込みchannelBeanで取得
     *
     * @param int $version 対象RSSバージョン指定
     *                    全バージョンのRSS  : rssLoader::VERSION_ALL
     *                    バージョン1.0のRSS : rssLoader::VERSION_1
     *                    バージョン2.0のRSS : rssLoader::VERSION_2
     *
     */
    public function loadRss($path, $version = self::VERSION_ALL) {
 
        /**
         * RSSを取得
         */
        $http = new httpConnecter();
        $http->connect($path);
        $rssStr = $http->loadText();
        if($rssStr === "") {
 
            // 取得できなければエラー
            throw rssException::notRss("RSSファイルの取得ができませんでした。");
        }
 
        /**
         * RSSを解析
         */
        $xml = new xmlLoader();
        $rssDom = $xml->parsor($rssStr);
 
        $channelBean = new channelBean();
 
        $channelBean->encoding = "UTF-8";
 
        // rss1.0
        if(isset($rssDom->attributes()->version) == false) {
            $channelBean->rssVersion = self::VERSION_1;
            $channelBean->rssUrl = $rssDom->channel->link;
 
            if($version != self::VERSION_1 && $version != self::VERSION_ALL) {
 
                throw rssException::notMatchVersion("このRSSはVertion1.0ではありません。");
            }
        }
        // rss2.0
        else if($rssDom->attributes()->version == 2) {
 
            $channelBean->rssVersion = self::VERSION_2;
            $channelBean->rssUrl = $rssDom->channel->link;
 
            if($version != self::VERSION_2 && $version != self::VERSION_ALL) {
 
                throw rssException::notMatchVersion("このRSSはVertion2.0ではありません。");
            }
        }
 
        // RSSの本体情報を取得
        if(isset($rssDom->channel->title)) {
            $channelBean->title = $rssDom->channel->title;
        }
        if(isset($rssDom->channel->link)) {
            $channelBean->link = $rssDom->channel->link;
        }
        if(isset($rssDom->channel->description)) {
            $channelBean->description = $rssDom->channel->description;
        }
        // dcの要素を取得
        $dc = $rssDom->channel->children('http://purl.org/dc/elements/1.1/');
        if(isset($dc->date)) {
            $channelBean->date = $dc->date;
        }
        if(isset($dc->language)) {
            $channelBean->language = $dc->language;
        }
        if(isset($dc->creator)) {
            $channelBean->creator = $dc->creator;
        }
 
        // 各記事を取得する
        foreach($rssDom->item as $item) {
 
            $itemBean = new itemBean();
 
            if(isset($item->title)) {
                $itemBean->title = $item->title;
            }
            if(isset($item->link)) {
                $itemBean->link = $item->link;
            }
            if(isset($item->description)) {
                $itemBean->description = $item->description;
            }
            if(isset($item->category)) {
                $itemBean->category = $item->category;
            }
            if(isset($item->pubDate)) {
                $itemBean->date = $item->date;
            }
            // dcの要素を取得
            $dc = $item->children('http://purl.org/dc/elements/1.1/');
            if(isset($dc->date)) {
                $itemBean->date = $dc->date;
            }
            if(isset($dc->subject)) {
                $itemBean->category = $dc->subject;
            }
            if(isset($dc->creator)) {
                $itemBean->creator = $dc->creator;
            }
 
            array_push($channelBean->itemList, $itemBean);
        }
 
        return $channelBean;
    }
}

rssLoaderで解析するとchannelBeanクラスが返却される。
このchannelBeanクラス内部にitemBeanのリストがありそこに個々の記事のデータがあるといった感じ
itemBeanがchannelBeanの内部にあるのはRSS2.0ではchannelタグの内部にitemタグがあるからといった理由から

使い方は以下
・rssTest.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
 
require_once "rssLoader.php";
 
$rssLoader = new rssLoader();
try {
    $channel = $rssLoader->loadRss("http://watch2ch.2chblog.jp/index.rdf");// ネットワーク上のファイルの場合
    //$channel = $rssLoader->loadRss("/var/www/html/rss.rdf");// ローカルファイルの場合
} catch (Exception $e) {
 
    echo $e->getMessage();
}
 
?>
<html lang="ja">
    <head>
        <meta charset="utf-8" />
        <title>RSS</title>
    </head>
 
    <body>
        <h2><?=$channel->title ?></h2>
        <table border="1">
            <tr>
                <th>タイトル一覧</th>
                <th>記事</th>
                <th>作成日</th>
            </tr>
            <?php foreach($channel->itemList as $item): ?>
            <tr>
                <td><?=$item->title ?></td>
                <td><?=$item->date ?></td>
            </tr>
            <?php endforeach; ?>
        </table>
    </body>
</html>

ソースコードのダウンロードはこちら:[download id=”1″]

これでRSSを読み込んで記事情報を取り出すことはできました。

次回に続きます。

追記
このrssLoaderにはRSS2.0が読み込めないバグがあります。
修正版は後日別の記事にて掲載いたします。