用PHP解析RSS / Atom提要的最佳方法


135

我目前正在使用Magpie RSS,但当RSS或Atom提要格式不正确时,有时会掉下来。还有其他使用PHP解析RSS和Atom提要的选项吗?


1
此请求存在一个问题,大多数Feed读者都在使用php的核心XML读者,如果XML没有按照XML标准的要求进行正确格式设置,那么您将不得不考虑不使用XML读者并使用XML的读者。但是,文本阅读器在服务器上的负载将大大增加。我知道这已经回答了,我只是让人们意识到使用XML提要阅读器的弊端
Barkermn01 2013年

1
切勿尝试解析无效的XML。责怪源头。
Lothar

Answers:


28

您的其他选项包括:



189
我不喜欢这样的“答案”,给出的链接没有任何评论。看起来像您在Google上搜索并链接到一些热门结果。特别是因为询问者具有一些RSS经验,并且需要更好的解析器。
duality_

3
如果有人需要一点建议,那么Last RSS是上面列出的三个中最简单的。只有1个文件可以“需要”,并且可以在5行内获取RSS,并具有不错的数组输出。
猛禽2014年


我使用了其中两个,LastRss似乎不足以提供一个功能齐全的帮助程序,而SimplePie有点太复杂了。我想尝试其他一些方法,但是对这些库的注释使人们更好地理解,而不仅仅是链接。
noob

169

我一直使用PHP内置的SimpleXML函数来解析XML文档。它是目前为数不多的具有直观结构的通用解析器之一,这使得为诸如RSS feed之类的特定内容构建有意义的类变得异常容易。此外,它将检测XML警告和错误,一旦发现任何警告,您就可以通过HTML Tidy(如ceejayoz所述)之类的源代码来运行源以对其进行清理并再次尝试。

考虑一下使用SimpleXML的非常粗糙,简单的类:

class BlogPost
{
    var $date;
    var $ts;
    var $link;

    var $title;
    var $text;
}

class BlogFeed
{
    var $posts = array();

    function __construct($file_or_url)
    {
        $file_or_url = $this->resolveFile($file_or_url);
        if (!($x = simplexml_load_file($file_or_url)))
            return;

        foreach ($x->channel->item as $item)
        {
            $post = new BlogPost();
            $post->date  = (string) $item->pubDate;
            $post->ts    = strtotime($item->pubDate);
            $post->link  = (string) $item->link;
            $post->title = (string) $item->title;
            $post->text  = (string) $item->description;

            // Create summary as a shortened body and remove images, 
            // extraneous line breaks, etc.
            $post->summary = $this->summarizeText($post->text);

            $this->posts[] = $post;
        }
    }

    private function resolveFile($file_or_url) {
        if (!preg_match('|^https?:|', $file_or_url))
            $feed_uri = $_SERVER['DOCUMENT_ROOT'] .'/shared/xml/'. $file_or_url;
        else
            $feed_uri = $file_or_url;

        return $feed_uri;
    }

    private function summarizeText($summary) {
        $summary = strip_tags($summary);

        // Truncate summary line to 100 characters
        $max_len = 100;
        if (strlen($summary) > $max_len)
            $summary = substr($summary, 0, $max_len) . '...';

        return $summary;
    }
}

2
您有一个没有开始标签的结束标签。;)
Talvi Watia 2010年

130
好吧,我有一个,但是SO的代码格式化程序正在吃掉它,因为它上面没有空行。在相关说明中,您没有以大写字母开头的句子。;)
Brian Cline 2010年

4
请更改$feed_uri = $feed_or_url;$feed_uri = $file_or_url;...除此之外,谢谢您提供此代码!效果很好!
蒂姆(Tim)

5
请注意,虽然此解决方案很棒,但只会解析当前形式的RSS feed。由于它们的架构不同,因此无法解析Atom feed。
2012年

9
请注意,eregi_replace现在已经过时,已被替换preg_replace,以及eregipreg_match。可以在此处此处分别找到文档。
ITS阿拉斯加

45

用4行,我将rss导入到数组中。

$feed = implode(file('http://yourdomains.com/feed.rss'));
$xml = simplexml_load_string($feed);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

对于更复杂的解决方案

$feed = new DOMDocument();
 $feed->load('file.rss');
 $json = array();
 $json['title'] = $feed->getElementsByTagName('channel')->item(0)->getElementsByTagName('title')->item(0)->firstChild->nodeValue;
 $json['description'] = $feed->getElementsByTagName('channel')->item(0)->getElementsByTagName('description')->item(0)->firstChild->nodeValue;
 $json['link'] = $feed->getElementsByTagName('channel')->item(0)->getElementsByTagName('link')->item(0)->firstChild->nodeValue;
 $items = $feed->getElementsByTagName('channel')->item(0)->getElementsByTagName('item');

 $json['item'] = array();
 $i = 0;

 foreach($items as $key => $item) {
 $title = $item->getElementsByTagName('title')->item(0)->firstChild->nodeValue;
 $description = $item->getElementsByTagName('description')->item(0)->firstChild->nodeValue;
 $pubDate = $item->getElementsByTagName('pubDate')->item(0)->firstChild->nodeValue;
 $guid = $item->getElementsByTagName('guid')->item(0)->firstChild->nodeValue;

 $json['item'][$key]['title'] = $title;
 $json['item'][$key]['description'] = $description;
 $json['item'][$key]['pubdate'] = $pubDate;
 $json['item'][$key]['guid'] = $guid; 
 }

echo json_encode($json);

2
我刚试过 它没有给出一个数组
samayo

您能给我您正在使用的RSS提要吗?
2014年

2
如果您想知道。看来他正在使用tumblr rss feed。Anytumblrsite.com/rss会为您提供相同的输出。
andrewk

3
用了4行,做得很好:)但我改写了第一行:$feed = file_get_contents('http://yourdomains.com/feed.rss'); 可能比文件+爆破的强度低
Guidouil 2014年

1
一行,$ feed = json_decode(json_encode(simplexml_load_file(' news.google.com/?output=rss')),true);
ask_io 2014年

21

我想介绍简单的脚本来解析RSS:

$i = 0; // counter
$url = "http://www.banki.ru/xml/news.rss"; // url to parse
$rss = simplexml_load_file($url); // XML parser

// RSS items loop

print '<h2><img style="vertical-align: middle;" src="'.$rss->channel->image->url.'" /> '.$rss->channel->title.'</h2>'; // channel title + img with src

foreach($rss->channel->item as $item) {
if ($i < 10) { // parse only 10 items
    print '<a href="'.$item->link.'">'.$item->title.'</a><br />';
}

$i++;
}

清晰简单的解决方案!效果很好。
约翰T

13

如果提要不是格式正确的XML,则应该拒绝它,没有例外。您有权将Feed创建者称为bozo

否则,您将为弄乱HTML最终结果铺平道路。


3
+1,您不应尝试解决任何格式不正确的XML。我们与他们的经历很糟糕,请相信我,这是很大的痛苦:(
Helen Neely

35
但是,程序员没有选择业务合作伙伴,而必须解析他们得到的东西。
Edmond Meinfelder 2011年

2
如果要构建通用的RSS / Atom提要阅读器怎么办?如果任何格式错误的xml文件都可以“混淆”您的HTML,那么Bozo是谁?;)在收到的信息上要放心。
yPhil

6

HTML Tidy库能够修复某些格式错误的XML文件。在将提要传递给解析器之前运行提要可能会有所帮助。


2

我使用SimplePie来解析Google阅读器供稿,并且效果很好,并具有不错的功能集。

当然,我还没有使用格式不正确的RSS / Atom提要进行测试,所以我不知道它如何处理这些提要,我认为Google完全符合标准!:)


1

我个人使用BNC Advanced Feed Parser-我喜欢易于使用的模板系统



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.