BLOG ENTRY

CakePHP1.2上で外部サイトのRSSを取得&表示[CakePHP]

cakephp

CakePHP1.2上で外部サイトのRSSを取得&表示します。
CakePHP1.2でRSSを出力する場合はこちらです。

いろんな方法がありますが、今回はこの3つを書いておきます。

1:CakePHPで標準で用意されている機能を使う
2:ZendFrameworkなど外部ライブラリを使う
3:Cronを使ってRSS情報をDBに保存

の3本です。(サザエさん)

ではさっそく。

1:CakePHPで標準で用意されてる機能を使う

コントローラーのアクション内で

uses('Xml');
$xml = new Xml('★RSSのURL★');
$xmlArr = Set::reverse($xml);

これで$xmlArr内に配列として入ります。これで終わりです。

2:ZendFrameworkなど外部ライブラリを使う

次に外部ライブラリを使う方法です。

まずZendframworkを使うには

/app/vendors/zend_init.php
<?php
ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . dirname(__FILE__));

これを書いて
/app/vendors/
ここにZendフォルダをごっそりアップロード。

で、使うコントローラー内で

App::import('Vendor', 'zend_init');
App::import('Vendor', 'Zend_Feed_Rss', array('file' => 'Feed' . DS . 'Reader.php'));

こんな感じで書いてやれば、CakePHP上でZendFrameworkクラスを使えます。他のPHPライブラリでも基本同じです。
この部分の書式は公式マニュアルを見ればわかりやすいです。

で、今回はZend内のZend_Feed_Readerクラスを使ってみました。
コントローラーで

function get_url()
{
    App::import('Vendor', 'zend_init');
    App::import('Vendor', 'Zend_Feed_Rss', array('file' => 'Feed' . DS . 'Reader.php'));

    $rss_url = $this->feed_url();
    foreach ($rss_url as $k => $v) {
        $feed = Zend_Feed_Reader::import($v);
        $data = array(
            'title'        => $feed->getTitle(),
            'link'         => $feed->getLink(),
            'dateModified' => $feed->getDateModified(),
            'description'  => $feed->getDescription(),
            'language'     => $feed->getLanguage(),
            'entries'      => array(),
        );

        foreach ($feed as $entry) {
            $edata = array(
                'title'        => $entry->getTitle(),
                'description'  => $entry->getDescription(),
                'dateModified' => $entry->getDateModified(),
                'author'       => $entry->getAuthor(),
                'link'         => $entry->getLink(),
                'content'      => $entry->getContent()
            );
            $data['entries'][] = $edata;
        }
    }
    $this->set('data', $data);
}

function feed_url()
{
    return array(
                    '★RSSのURL1★',
                    '★RSSのURL2★'
                );
}

こんな感じでいけました。

3:Cronを使ってRSS情報をDBに保存

Cronを使って定期的にRSSを取得&DB保存するサンプルコードです。
こちらのページで素晴らしいmodelのコードが紹介されていたので参考にさせて頂きました。
ありがとうございます。

$ vi /etc/crontab

*/15 * * * * root /bin/bash ★ディレクトリ★/app/vendors/shells/tasks/cron.sh

$ vi /app/vendors/shells/tasks/cron.sh

#!/bin/bash
/usr/bin/curl http://example.com/feeds/save_rss

$ vi /app/models/feed.php

<?php
uses('Xml');

class Feed extends AppModel {
    var $name           = 'Feed';
    var $cacheDuration  = '+3 hours';

    function getAndSaveRss($options = array())
    {
        $default = array(
            'url'       =>  null,
            'limit'     =>  null,
            'categiry'  =>  null,
            'save'      =>  null,
            'offset'    =>  0,
        );
        $options = am($default, $options);
        $this->_parse($options);
    }

    function _parse($options)
    {
        $xml = new Xml($options['url']);
        $xml = Set::reverse($xml);

        $i = 0;
        // RSS1.0
        if (isset($xml['RDF'])) {
            $title = $xml['RDF']['Channel']['title'];
            $link = $xml['RDF']['Channel']['link'];

            $items = array();
            foreach ($xml['RDF']['Item'] as $key => $item) {
                if ($i >= $options['limit']) {
                    break;
                }
                $items[$key]['site_title']  = $title;
                $items[$key]['category']    = $options['category'];
                $items[$key]['site_url']    = $link;
                $items[$key]['pubDate']         = date('Y-m-d H:i:s', strtotime($item['date']));
                $items[$key]['title']           = $item['title'];
                $items[$key]['link']            = $item['link'];
                if (isset($item['encoded'])) {
                    $items[$key]['description'] = $item['encoded'];
                } else if (isset($item['description'])) {
                    $items[$key]['description'] = $item['description'];
                }

                if ($options['save'] == 1) {
                    $this->save_rss($items[$key]);
                }
                $i++;
            }
        }
        // RSS2.0
        elseif (isset($xml['Rss'])) {
            $title = $xml['Rss']['Channel']['title'];
            if (isset($xml['Rss']['Channel']['link'])) {
                $link = $xml['Rss']['Channel']['link'];
            } elseif (isset($xml['Rss']['Channel']['Link']['0'])){
                $link = $xml['Rss']['Channel']['Link']['0'];
            }
            $items = array();
            foreach ($xml['Rss']['Channel']['Item'] as $key => $item) {
                if ($i >= $options['limit']) {
                    break;
                }
                $items[$key]['site_title']  = $title;
                $items[$key]['category']    = $options['category'];
                $items[$key]['site_url']    = $link;
                if (isset($item['pubDate'])) {
                    $items[$key]['pubDate']     = date('Y-m-d H:i:s', strtotime($item['pubDate']));
                } else if (isset($item['date'])) {
                    $items[$key]['pubDate']     = date('Y-m-d H:i:s', strtotime($item['date']));
                }
                $items[$key]['title']       = $item['title'];
                if (isset($item['link'])) {
                    $items[$key]['link'] = $item['link'];
                } else if (isset($item['guid']['value'])) {
                    $items[$key]['link'] = $item['guid']['value'];
                }
                $items[$key]['description'] = $item['description'];

                if ($options['save'] == 1) {
                    $this->save_rss($items[$key]);
                }
                $i++;
            }
        }
        // Atom
        elseif (isset($xml['Feed'])) {
            $title = $xml['Feed']['title'];
            if (isset($xml['Feed']['Link']['href'])) {
                $link = $xml['Feed']['Link']['href'];
            } else if (isset($xml['Feed'][0]['Link']['href'])) {
                $link = $xml['Feed'][0]['Link']['href'];
            }
            $items = array();
            foreach ($xml['Feed']['Entry'] as $key => $item) {
                if ($i >= $options['limit']) {
                    break;
                }
                $items[$key]['site_title']  = $title;
                $items[$key]['category']    = $options['category'];
                if (isset($link)) {
                    $items[$key]['site_url']    = $link;
                } else {
                    $items[$key]['site_url']    = $item['content']['xml:base'];
                }
                $items[$key]['pubDate']     = date('Y-m-d H:i:s', strtotime($item['issued']));
                $items[$key]['title']       = $item['title'];
                $items[$key]['link']        = $item['Link']['href'];
                $items[$key]['description'] = $item['content']['value'];

                if ($options['save'] == 1) {
                    $this->save_rss($items[$key]);
                }
                $i++;
            }
        }
        else {
            return false;
        }
        return compact('title', 'link', 'items');
    }

    function save_rss($data)
    {
        $limit_title = $this->limit_title();
        foreach ($limit_title as $v) {
            if (strpos($data['title'], $v) !== FALSE) {
                return FALSE;   //広告などは外す
            }
        }

        $this->data['Feed'] = array();

        $sql = array(
                    'conditions' => array(
                                            'site_title' => $data['site_title'],
                                            'title'      => $data['title'],
                                            'link'       => $data['link']
                                         )
                    );

        $feed = $this->find('first', $sql);
        $this->data['Feed'] = $data;
        if ($feed !== FALSE) {
            $this->data['Feed']['id'] = $feed['Feed']['id'];    //update文にする
        } else {
            $this->data['Feed']['id'] = NULL;                   //insert文にする
        }

        $return = $this->save($this->data['Feed']);
    }

    function limit_title() {
        return array(
                    'AD',
                    'PR'
                    );
    }
}

$ vi /app/controllers/components/feed_rss.php

<?php

class FeedRssComponent extends Object
{
    var $controller;

    function initialize(&$controller) {
        $this->controller =& $controller;
    }

    function get_rss($limit = 5)
    {
        $feedArr = $this->feed_site();

        foreach ($feedArr as $v) {
            $url        = $v['url'];
            $category   = $v['category'];
            $save       = 1;
            $this->controller->Feed->getAndSaveRss(compact('url', 'category', 'limit', 'save'));
        }
    }

    function set_rss($limit = 10)
    {
        $sql = array(
                    'conditions'    => array('OR' => array("Feed.category = 'webdesign '", "Feed.category = 'design'")),
                    'order'         => 'Feed.pubDate DESC',
                    'group'         => 'Feed.title',
                    'limit'         => $limit,
                    );
        $rssArr = $this->controller->Feed->find('all', $sql);
        $this->controller->set('rssArr', $rssArr);
    }

    function remakeFeed($rssArr)
    {
        for ($i = 0; $i < count($rssArr); $i++) {
            $rssArr[$i]['Feed']['pubDate'] = substr($rssArr[$i]['Feed']['pubDate'], 0, 4) . '-' . substr($rssArr[$i]['Feed']['pubDate'], 5, 2) . '-' . substr($rssArr[$i]['Feed']['pubDate'], 8, 2);
        }
        return $rssArr;
    }
    function feed_site()
    {
        return array(
                    '★RSSのURL1★',
                    '★RSSのURL2★',
                    '★RSSのURL3★',
                    '★RSSのURL4★',
                    '★RSSのURL5★',
                    '★RSSのURL6★',
                    '★RSSのURL7★'
                );
    }
}

で、表示したいコントローラーのアクション内で

$this->FeedRss->set_rss(15);

とかでビューにデータを渡します。

終わり。

関連記事

  1. CakePHP1.2でRSS2.0を出力する[RSS][CakePHP]
  2. 外部複数ブログのRSS情報をWordPress上で表示する[WordPress]
  3. ページの短縮URLを貼り付けたTwitter投稿をしてもらう
  4. アソシエーションを絡めたcountで件数がとれない&エラー[CakePHP]
  5. 文字列を、1行上限★バイトで改行させて、上限★行まで表示する[PHP]

WRITE COMMENT


(required)


(required)


(required)

MENU