本文目录导读:

在 PHP 中实现订阅源(RSS/Atom)功能,通常涉及两种情况:生成订阅源(作为发布者)和读取订阅源(作为订阅者),下面分别介绍。
生成订阅源(作为发布者)
如果你想让用户订阅你的网站内容,需要用 PHP 生成 RSS 或 Atom 格式的 XML 文件。
手动生成 RSS 2.0 示例
<?php类型为 XML
header('Content-Type: application/rss+xml; charset=utf-8');
// 数据库或数组中获取最新文章
$articles = [
[
'title' => '文章标题 1',
'link' => 'https://example.com/article/1',
'description' => '这是文章摘要...',
'pubDate' => date('D, d M Y H:i:s O', strtotime('2025-01-01 10:00:00')),
'author' => '作者名'
],
// 更多文章...
];
// 生成 RSS XML
echo '<?xml version="1.0" encoding="UTF-8"?>';
?>
<rss version="2.0">
<channel>你的网站标题</title>
<link>https://example.com</link>
<description>网站描述</description>
<language>zh-cn</language>
<?php foreach ($articles as $article): ?>
<item>
<title><?php echo htmlspecialchars($article['title']); ?></title>
<link><?php echo $article['link']; ?></link>
<guid><?php echo $article['link']; ?></guid>
<description><?php echo htmlspecialchars($article['description']); ?></description>
<pubDate><?php echo $article['pubDate']; ?></pubDate>
<author><?php echo $article['author']; ?></author>
</item>
<?php endforeach; ?>
</channel>
</rss>
使用 PHP 库生成
推荐使用 Laminas Feed 或 SimplePie(读取用)。
用 Laminas Feed 生成:
composer require laminas/laminas-feed
<?php
use Laminas\Feed\Writer\Feed;
$feed = new Feed();
$feed->setTitle('网站标题');
$feed->setLink('https://example.com');
$feed->setDescription('网站描述');
// 添加条目
$entry = $feed->createEntry();
$entry->setTitle('文章标题');
$entry->setLink('https://example.com/article/1');
$entry->setDateModified(time());
$entry->setDescription('#39;);
$feed->addEntry($entry);
// 输出 RSS 2.0
echo $feed->export('rss');
读取订阅源(作为订阅者)
如果你想读取别人的 RSS/Atom 源。
使用 SimplePie(推荐)
SimplePie 是 PHP 中最流行的订阅源解析库。
安装:
composer require simplepie/simplepie
基本用法:
<?php
require_once 'vendor/autoload.php';
use SimplePie\SimplePie;
// 设置缓存目录(需要可写)
$feed = new SimplePie();
$feed->set_feed_url('https://example.com/feed.xml');
$feed->set_cache_location('./cache');
$feed->init();
$feed->handle_content_type();
// 检查是否成功
if ($feed->error()) {
echo '读取失败: ' . $feed->error();
exit;
}
// 获取订阅源信息
echo '标题:' . $feed->get_title() . '<br>';
echo '网站:' . $feed->get_link() . '<br>';
echo '描述:' . $feed->get_description() . '<br>';
// 遍历文章
foreach ($feed->get_items() as $item) {
echo '<h2>' . $item->get_title() . '</h2>';
echo '<a href="' . $item->get_link() . '">阅读原文</a><br>';
echo '发布时间:' . $item->get_date('Y-m-d H:i') . '<br>';
echo $item->get_description() . '<br><hr>';
}
使用 cURL + DOMDocument(原生方法)
<?php
function fetchRss($url) {
// 使用 cURL 获取内容
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$xml = curl_exec($ch);
curl_close($ch);
return $xml;
}
// 解析 XML
$xmlStr = fetchRss('https://example.com/feed');
$xml = simplexml_load_string($xmlStr, 'SimpleXMLElement', LIBXML_NOCDATA);
// 使用命名空间
$namespaces = $xml->getNamespaces(true);
$content = $xml->channel;
foreach ($content->item as $item) {
echo '标题:' . $item->title . '<br>';
echo '链接:' . $item->link . '<br>';
echo '描述:' . $item->description . '<br>';
// 如果有扩展命名空间
if (isset($item->children($namespaces['content']))) {
$contentExt = $item->children($namespaces['content']);
echo '全文:' . html_entity_decode((string)$contentExt->encoded) . '<br>';
}
echo '<hr>';
}
实用技巧
统一封装读取函数
<?php
class FeedReader {
private $feed;
public function __construct($url) {
$this->feed = new SimplePie();
$this->feed->set_feed_url($url);
$this->feed->enable_cache(true);
$this->feed->set_cache_duration(3600); // 1小时缓存
$this->feed->init();
}
public function getItems($limit = 20) {
$items = [];
foreach ($this->feed->get_items(0, $limit) as $item) {
$items[] = [
'title' => $item->get_title(),
'link' => $item->get_link(),
'description' => $item->get_description(),
'date' => $item->get_date('Y-m-d H:i:s'),
'author' => $item->get_author() ? $item->get_author()->get_name() : '',
'image' => $this->extractImage($item->get_content()),
'categories' => $this->getCategories($item)
];
}
return $items;
}
private function extractImage($content) {
if (preg_match('/<img[^>]+src="([^"]+)"/', $content, $matches)) {
return $matches[1];
}
return '';
}
private function getCategories($item) {
$cats = $item->get_categories();
return $cats ? array_map(function($cat) {
return $cat->get_label();
}, $cats) : [];
}
}
// 使用
$reader = new FeedReader('https://example.com/feed');
$articles = $reader->getItems(10);
foreach ($articles as $article) {
echo $article['title'] . ' (' . $article['date'] . ')<br>';
}
使用 WordPress 方式(如果使用 WP)
// 获取订阅源
$rss = fetch_feed('https://example.com/feed');
if (!is_wp_error($rss)) {
$maxitems = $rss->get_item_quantity(5);
$rss_items = $rss->get_items(0, $maxitems);
foreach ($rss_items as $item) {
echo '<a href="' . $item->get_permalink() . '">';
echo $item->get_title();
echo '</a>';
}
}
安全建议
- 过滤输出:所有动态内容输出前使用
htmlspecialchars()防止 XSS。 - 设置头信息:正确设置
Content-Type为application/rss+xml或text/xml。 - 缓存:读取外部订阅源一定用缓存避免每次都请求。
- 超时处理:设置 cURL 超时,避免卡死页面。
- 错误处理:检查 XML 解析结果,处理无效 XML。
- CDATA 处理如果含特殊字符,用 CDATA 包裹:
<description><![CDATA[<?php echo $article['description']; ?>]]></description>
最佳实践
- 生成时:确保每个 item 都有唯一
<guid>。 - 生成时:
pubDate使用 RFC 822 格式(date(DATE_RFC2822))。 - 读取时:注意处理编码问题(UTF-8)。
- 读取时:处理图片懒加载(部分订阅源用
data-src)。 - 避免过度调用:大量外部订阅源请求可能导致被封或加载缓慢。
如果需要更高级功能(如 WebSub 实时推送),可以考虑使用 WebSub/PubSubHubbub 协议配合实现。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播