昨天学习了一下 RSS 订阅知识之后,经过一番百度搜索,终于在自己的博客上实现了 RSS 订阅功能,但苦于技术有限,不能对 Feed 文件进行定时缓存,每次打开链接都会比较延迟。今天继续对这个功能进行了学习,突然,我发现了一个大佬提供的 rssphp 代码,有了他,很多实用功能不再需要自己去分析、判断和写代码了,最重要的是他提供了定时缓存 xml 文件的功能,于是将其拿来,在经过一番操作之后,终于在自己的博客上较为完美的实现了。
文档修改日志:
- 2024.12.01 实现 rss 订阅
- 2024.12.02 增加 atom 订阅,修复截取字符串乱码问题
一、下载代码存到自己的博客
上面的链接可以下载下来学习,里面也有两个 demo 文件供参考,但放入博客,真正要用的只需要 Feed.php 文件,我将其存放到自己主题目录下面,然后在 funciton.php 文件中引入(通常是放在函数代码块的前面,方便以后回忆代码)。
include_once 'path/to/feed.php';
二、建立 Feed 文件下载缓存目录
就用 demo 中所说的 tmp 目录吧,在主题目录下面建立 tmp 目录,并赋权为 777(linux系统)
sudo chmod 777 -R tmp
三、在主题目录下建立模板文件 rss.php 实现订阅
下面是我写的模板文件,重点看订阅RSS部分的php代码,主要实现了几个功能
- 指定时区(不知道啥用)以及指定缓存位置及下载缓存文件的时间间隔
- 获取 RSS 订阅网址及 atom 订阅网址数据
- 对每个 RSS 文件进行读取和输出相关信息
- 加入了 try 防止有些 feed 文件不被识别而报错
<?php
/**
* RSS自动订阅
*
* @package custom
*/
?>
<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<?php $this->need('header.php'); ?>
<!-- main-body -->
<div class="p-3 flex-1">
<!-- 文章 -->
<article class="flex flex-col mb-6">
<!--标题-->
<div
class="mb-6 p-2 flex flex-col hyone-box">
<p
class="p-3 text-lg md:text-xl lg:text-2xl text-slate-900 line-clamp-1 font-extrabold tracking-tight dark:text-slate-300 ">
<a itemprop="url"
href="<?php $this->permalink() ?>"><?php $this->title() ?></a>
</p>
<div class="px-3 text-base line-clamp-2 lg:line-clamp-3 mb-2">
<p></p>
</div>
</div>
<!-- 正文 -->
<div
class="mb-6 p-2 flex-1 flex flex-col hyone-box">
<div class="px-3 md:px-6 py-6 text-base leading-9 mb-2 flex-1">
<!-- 订阅基础设置 -->
<?php
// 指定时区
if (!ini_get('date.timezone')) {
date_default_timezone_set('Asia/Shanghai');
}
// 指定缓存目录及缓存事件
Feed::$cacheDir = __DIR__ . '/tmp';
Feed::$cacheExpire = '6 hours';
?>
<!-- 订阅RSS开始 -->
<?php
// 获取需要订阅RSS的网址
$delimiter = ",";
if ($this->options->rss) {
$rssfeed = explode($delimiter, $this->options->rss);
} else {
$rssfeed = array(
"https://www.zhangxinxu.com/wordpress/feed/",
"https://www.hollowman.cn/feed/"
);
}
//调用每个RSS文件
for ($i = 0; $i < count($rssfeed); $i++) {
$rssname = 'rss' . $i;
try {
$$rssname = Feed::loadRss($rssfeed[$i]);
echo ' <div class="accordion">';
echo ' <div class="accordion-title">' . htmlspecialchars($$rssname->title) . '</div>';
echo '<div class="accordion-body"><div>';
foreach ($$rssname->item as $item):
if (strlen($item->title) > 0) {
$description = mb_substr(trim(strip_tags($item->description)), 0, 150);
echo '<div class="rsspost"><a href="' . htmlspecialchars($item->url) . '" target="_blank" rel="noopener">' . htmlspecialchars($item->title) . '</a>(' . date('Y-n-j', (int) $item->timestamp) . ')<br><span class="line_over_hidden">' . htmlspecialchars($description) . '</span></div>';
}
endforeach;
echo '</div>';
echo '</div>';
echo '</div>';
} catch (Exception $e) {
}
}
?>
<!-- 订阅RSS结束 -->
<!-- 订阅 atom 开始 -->
<?php
// 获取需要订阅 atom 的网址
$delimiter = ",";
if ($this->options->atom) {
$atomfeed = explode($delimiter, $this->options->atom);
} else {
$atomfeed = array(
"http://www.ruanyifeng.com/blog/atom.xml"
);
}
//调用每个 atom 文件
for ($i = 0; $i < count($atomfeed); $i++) {
$atomname = 'atom' . $i;
try {
$$atomname = Feed::loadAtom($atomfeed[$i]);
echo ' <div class="accordion">';
echo ' <div class="accordion-title">' . htmlspecialchars($$atomname->title) . '</div>';
echo '<div class="accordion-body"><div>';
foreach ($$atomname->entry as $entry):
if (strlen($entry->title) > 0) {
$content = mb_substr(trim(strip_tags($entry->content)), 0, 150);
echo '<div class="rsspost"><a href="' . htmlspecialchars($entry->url) . '" target="_blank" rel="noopener">' . htmlspecialchars($entry->title) . '</a>(' . date('Y-n-j', (int) $entry->timestamp) . ')<br><span class="line_over_hidden">' . htmlspecialchars($content) . '</span></div>';
}
endforeach;
echo '</div>';
echo '</div>';
echo '</div>';
} catch (Exception $e) {
}
}
?>
<!-- 订阅 atom 结束 -->
</div>
<div class="flex-1 px-3 md:px-6 py-6 post-content">
</div>
</div>
</article>
</div>
<style>
.rsspost {
padding: 0 1rem;
}
.rsspost:hover {
background-color: rgba(0, 0, 0, .2);
}
.rsspost a {
color: green;
font-weight: bolder;
}
.rsspost a:hover {
color: yellowgreen;
}
/* 超出隐藏 */
.line_over_hidden {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
</style>
<?php $this->need('sidebar.php'); ?>
<?php $this->need('footer.php'); ?>
订阅 RSS 来源,我是通过在主题外观中添加了一个 input 框,将需要订阅的地址写入后进行订阅,如果后台不写入,则在此文件中添加默认的订阅网址。
可以在 function.php 文件的 themeConfig($form)
函数中写入订阅 input 框
//主题配置
function themeConfig($form){
...
// rss订阅链接
$rss = new \Typecho\Widget\Helper\Form\Element\Text('rss', null, null, _t('rss订阅链接'), _t('添加需要订阅的rss地址,以逗号分割'));
$form->addInput($rss);
// atom订阅链接
$atom = new \Typecho\Widget\Helper\Form\Element\Text('atom', null, null, _t('atom订阅链接'), _t('添加需要订阅的atom地址,以逗号分割'));
$form->addInput($atom);
...
}