Archive
Zend_Feed打造Feed Reader
作者:Haohappy
来源:http://www.phpeye.com]PHPEye.com
最后更新:2006-12-19 15:41:24
相信对于很多人来说,通过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)";
$query .=" 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中英翻译平台的一部份,该平台尚在开发当中。
Tags/标签: php, zend frameworkRelated posts
群众的眼睛是雪亮的
陈近南:斩过鸡头,烧过黄纸,歃血为盟之后,韦小宝你就是我天地会的兄弟,暂时编入青木堂。我们有十大会规,二十大守则,三十大戒条,八十小戒条,如果犯了其中一条的话,就算你是我的徒弟,也要身受九九八十一刀而死。
韦小宝:不用那么费力,我一刀就死了。
陈近南:不要乱说话,起来!青木堂堂主惨死在熬拜爪牙的手上,我们一定要贯彻他的遗志,诛杀熬拜这个奸贼!同时,将满清皇帝跟清狗赶出关外,复我大明江山!
众人:反清复明!反清复明!反清复明!
韦小宝:反清复明!反清复明!
陈近南:现在我有一个极为危险的任务,希望能有兄弟自愿担任。
众人:有任务,有任务!
陈近南:我查到清宫里面有四本《四十二章经》,里面记载了清廷在关外收藏一个大宝藏的秘密。如果我们能够知道这个大宝藏的秘密,我们就可以取回清朝在大明江山所搜刮的民脂民膏,而且还可以切断他们的龙脉!
众人:有道理!
陈近南:龙脉一断,那清狗的气数就已尽!而我们大明江山就指日可复!所以我想派人入宫去偷这几本经书!但是我知道这个任务非常的危险,可以说是九死一生,有谁不想去的就坐下!
众人:(纷纷拼死占座,韦小宝只因要坐的椅子上被陈近南钉了钉子而站了起来。)
陈近南:小宝,想不到你一加入本会就想立此奇功!
韦小宝:是呀!
陈近南:好,为师就成全你!
韦小宝:不是啊!因为真相是这样的,这把椅子……
陈近南:大丈夫一言九鼎,你知不知道背信弃义是犯了本会会规第八条,要斩一手一脚!
韦小宝:啊?这到底是天地会还是整人会啊!
陈近南:你跟我进来!
陈近南:小宝,你是个聪明人,我可以用聪明的方法跟人说话。外面的人就不行!
韦小宝:不解!
陈近南:读过书明事理的人,大多数已经在清廷里面当官了。所以我们要对抗清廷,就要用一些蠢一点的人。对付那些蠢人,就绝对不可以跟他们说真话,必须要用宗教形式来催眠他们,使他们觉得所做的事都是对的,所以“反清复明”只不过是个口号,跟“阿弥陀佛”其实是一样的。清朝一直欺压我们汉人,抢走我们的银两跟女人,所以我们要反清。
韦小宝:要反清抢回我们的钱跟女人,是不是,复不复明根本就是脱了裤子放屁,关人鸟事呀!行了,大家聪明人,了解!继续!
陈近南:总之,如果成功的话,就有无数的银两跟女人,你愿不愿意去呀?
韦小宝:愿意!只不过你刚才那句“九死一生”太吓人了!。。。
群众的眼睛真TMD亮啊 ….
Tags/标签: 随便写写