首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 利用 SimpleXML 解析 RSS 訂閱聚合文章

     編輯:PHP 相關知識

RSS 2.0 結構速覽

<rss version="2.0">
  <channel>
    <title>頻道標題</title>
    <link>https://example.com</link>
    <description>頻道描述</description>
    <item>
      <title>文章標題</title>
      <link>https://example.com/post/1</link>
      <description><![CDATA[文章摘要...]]></description>
      <pubDate>Mon, 01 Jan 2024 12:00:00 +0800</pubDate>
      <guid>https://example.com/post/1</guid>
      <category>分類</category>
    </item>
    ...
  </channel>
</rss>

核心解析代碼

<?php
/**
 * 獲取 RSS 項目列表
 * @param string $feedUrl
 * @param int    $limit    最大條數
 * @return array           [['title','link','desc','date','guid'], ...]
 */
function fetchRssItems(string $feedUrl, int $limit = 20): array {
    $ctx = stream_context_create([
        'http' => [
            'timeout' => 10,
            'user_agent' => 'Mozilla/5.0 (compatible; RSSReader/1.0)',
        ],
        'ssl' => ['verify_peer' => false, 'verify_peer_name' => false], // 兼容自簽證書
    ]);

    $xml = @simplexml_load_file($feedUrl, 'SimpleXMLElement', LIBXML_NOCDATA, $ctx);
    if (!$xml) {
        error_log("RSS parse failed: $feedUrl");
        return [];
    }

    $items = [];
    foreach ($xml->channel->item as $item) {
        $items[] = [
            'title'       => (string)$item->title,
            'link'        => (string)$item->link,
            'description' => (string)$item->description,
            'pubDate'     => isset($item->pubDate) ? strtotime((string)$item->pubDate) : time(),
            'guid'        => (string)($item->guid ?? $item->link),
            'category'    => (string)($item->category ?? ''),
        ];
        if (count($items) >= $limit) break;
    }
    return $items;
}

// 使用示例
$feeds = [
    'https://rss.sina.com.cn/news/world/focus15.xml',
    'https://feeds.bbci.co.uk/news/world/rss.xml',
];

foreach ($feeds as $feed) {
    $articles = fetchRssItems($feed, 5);
    echo "<h2>$feed</h2><ul>";
    foreach ($articles as $a) {
        echo "<li><a href='{$a['link']}' target='_blank'>{$a['title']}</a> ";
        echo "<small>" . date('Y-m-d H:i', $a['pubDate']) . "</small></li>";
    }
    echo "</ul>";
}

關鍵參數解析

  • `LIBXML_NOCDATA`:將 CDATA 內容直接作為文本節點讀取,避免 `SimpleXMLElement` 對象包裹。
  • `stream_context_create`:設置超時、User-Agent、SSL 驗證策略,防止卡死或證書錯誤。
  • `(string)$node`:強制轉換為字符串,而非對象。

進階:聚合多源並按時間排序

function aggregateFeeds(array $feedUrls, int $total = 30): array {
    $all = [];
    foreach ($feedUrls as $url) {
        $all = array_merge($all, fetchRssItems($url, 20));
    }
    // 按發布時間倒序
    usort($all, fn($a, $b) => $b['pubDate'] <=> $a['pubDate']);
    return array_slice($all, 0, $total);
}

緩存策略(生產必備)

function fetchRssCached(string $url, int $ttl = 300): array {
    $key = 'rss_' . md5($url);
    $data = apcu_fetch($key); // 或 Redis/Memcached
    if ($data !== false) return $data;

    $data = fetchRssItems($url);
    apcu_store($key, $data, $ttl);
    return $data;
}

異常格式兼容

法律與禮儀

  • 遵守 `robots.txt` 及站點服務條款。
  • 設置合理 User-Agent,標明爬蟲身份。
  • 請求間隔 ≥ 30 分鐘,或使用條件請求(`If-Modified-Since` / `ETag`)。
  • 僅聚合允許轉載/摘要的內容,保留原文鏈接與版權聲明。

總結

`simplexml_load_file()` + `LIBXML_NOCDATA` 是 PHP 解析 RSS/Atom 最輕量高效的組合。配合緩存、超時、異常兼容,即可構建穩健的內容聚合服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
異常情況處理方式
Atom 1.0 (feed 標簽)檢測 `$xml->getName() === 'feed'`,解析 `entry` 而非 `item`
命名空間 (dc:creator, media:content)`$item->children('dc', true)->creator`
編碼非 UTF-8`simplexml_load_file` 自動按 XML 聲明解碼,若亂碼用 `mb_convert_encoding`
超大文件 (>10MB)改用 `XMLReader` 流式解析