首页 > 开发 > PHP > 正文

使用Zend_Feed+Cron打造Feed Reader

2024-05-04 22:59:21
字体:
来源:转载
供稿:网友
相信对于很多人来说,通过bloglines,google reader这些阅读器订阅和浏览blog已经是网络生活的一部份。如果你打算自己打造一个好用的feed reader,不妨试试zend_feed这个好用的类库。

首先大概的原理是读取blog的rss或atom feed,得到xml文件,解析该文件得到数据。为了加快浏览速度,我们通常需要把得到数据保存到本地数据库中。

以上目的分解成技术步骤有以下三步:
1。读取rss。 你可以使用现成的函数或者专业的rss类库(这种类库一般还提供更多丰富的功能),也可以自己模拟http来抓取;

在php中,使用简单的比如file_get_contents()函数就可以方便而且高效地抓取文件,但有时候可能rss文件是不能直接获取的,比如获取你的bloglines帐号中订阅的rss,那么可能你还需要提交一些参数或者通过http认证之类,这时可用模拟http的方法,比如下面代码使用了pear::http_request:

function getrss($username,$password,$s,$n=0){
       
        
$url "http://rpc.bloglines.com/getitems?s=".$s."&n=".$n;

        
$req = & new http_request($url);
        
$req->setbasicauth($username,$password);
        
$req->sendrequest();

        
$blogcontent $req->getresponsebody();
        return 
$blogcontent;

    }

填入你的bloglines帐号和密码,利用这个函数你就可以得到rss文件。

2。解析xml rss文件遵循一定规范,你可以自己写个函数来解析,没什么难度,但有点繁琐。
3。将解析得到的数据入库。

好了,大概知道了要做的工作,你会发现虽然都不难,但是自己一个个实现比较麻烦,呵呵。这就是本文要介绍zend_feed的原因。

zend_feed是zend framework中的一个类库,我们完全可以把它单独拿出来使用。zend_feed高度封装,使用非常方便,例如读取一个rss feed:


$channel = new zend_feed_rss('http://rss.example.com/channelname');
echo 
$channel->title();

//遍历记录
foreach ($channel as $item) {
    echo 
$item->title() . "/n";
}

是不是非常简单? 读取和解析总共5行代码。

好,下面我们开始完成一个真正的feed reader:

feedreader.php

<?php
set_time_limit
(0);
define('zend_dir','/www/lib');
set_include_path(get_include_path().path_separator.zend_dir);
require_once(
'zend.php');
zend::loadclass('zend_feed');
zend::loadclass('zend_filter_input');

$link mysql_connect('localhost''user''pwd')
    or die(
'could not connect: ' mysql_error());
//echo 'connected successfully';
mysql_select_db('phpeye') or die('could not select database');


$feedchannel = array(
                    
'http://www.phpdeveloper.org/phpdev.rdf',
                    
'http://www.planet-php.net/rss/'
            
);

foreach (
$feedchannel as $channel) {
    
readrssfeed($channel);
}

echo 
"done!";

function 
readrssfeed($feedaddress){

        try {            
            
$rss zend_feed::import($feedaddress);
        } catch (
zend_feed_exception $e) {
         
// feed 导入失败
         //echo "exception caught importing feed: {$e->getmessage()}/n";
                 
$msg "exception caught importing feed: {$e->getmessage()}/n ";
                 
$datetime date("y-m-d h:i:s",time());
                 
$errmsg $msg.' '.$datetime."/n/n";                                   

                 echo 
$errmsg;  
                 
file_put_contents('feedreader.log',$errmsg,file_append);
         exit;
        }

        
// 初始化保存 channel 数据的数组,$rss内部数据只能通过调用类方法才能访问
        
$channel = array(
         
'title'       => $rss->title(),
         
'link'        => $rss->link(),
         
'description' => $rss->description(),
         
'items'       => array()
        );

            
$count=0;    
        
// 循环获得channel的item并存储到相关数组中
        
foreach ($rss as $item) {

            
             
$channel['items'][] = array(
                
'title'       => $item->title(),
                
'link'        => $item->link(),
                
'description' => $item->description()
                );
            
            

             //标题和内容都需要转义
             
$title strip_tags(mysql_real_escape_string($item->title()));
             
$link strip_tags($item->link());         
             
$description mysql_real_escape_string($item->description());        
             
             
//先查询数据库看记录是否已经存在,存在则不操作,否则向数据库添加新记录
             
$query "select * from feedentry where entitle = '$title'";
             
//echo "<hr>sql: ".$query."<p>/n/r";
              
$result mysql_query($query) or die('query failed: ' mysql_error());
              
$num_rows mysql_num_rows($result);

              if(
$num_rows 0) {
                  
//echo "the record already exists! ";
                  //do nothing...
              
}else{
                 
$query "insert into feedentry (entitle,link,endescription,addtime) values ('$title','$link','$description',now())";
                 
//echo "<hr>sql: ".$query."<p>/n/r";

                 
$result mysql_query($query) or die('query failed: ' mysql_error());

                                 
$count++;
              }

        }

        
//zend::dump($channel);
                
$datetime date("y-m-d h:i:s",time());
                
                if(
$count>0){
                    
$msg $count." entrys read successfully! ".$datetime."/n/n";
                    echo 
$msg;
                    
file_put_contents('feedreader.log',$msg,file_append);
                }else{
                    
$msg 'read nothing...'.$datetime."/n/n";
                    echo 
$msg;
                    
file_put_contents('feedreader.log',$msg,file_append);
                }              
                
    }

?>

文件中除了rss读取,解析和入库外,还有debug和日志功能。

数据表结构如下:

create table `feedentry` (
  `id` int(11) not null auto_increment,
  `entitle` varchar(200) not null default '',
  `link` varchar(200) not null default '',
  `endescription` mediumtext not null,
  `category` varchar(50) not null default '',
  `comments` text not null,
  `publishtime` datetime not null default '0000-00-00 00:00:00',
  `addtime` datetime not null default '0000-00-00 00:00:00',
  primary key  (`id`)
) type=myisam ;


呵呵
,把这个文件保存。然后利用linux的cron脚本让它定时在命令行下运行,下面让它每小时的40分运行一次:
crontab -e
40  *   *   *   *   /usr/local/bin/php -q /www/phpeye/feedreader.php

一个好用的feed reader就打造完成了。如果你想添加rss频道,可以自己在$feedchannel这个数组中添加元素,非常方便,当然如果你有兴趣,可以写一个web界面来管理,那样就更方便了。

改进:

这个reader已经具备了核心功能,但是没有完成频道管理功能,你可以再建一个feedchannel数据表,并且在feedentry表中增加一个channelid字段,这样就可以随意增添管理feed频道了。

效果请看:http://www.phpeye.com

本文介绍的程序属于phpeye blog中英翻译平台的一部份,该平台尚在开发当中。

<end>



发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表