使用jQuery解析RSS

194

我希望使用jQuery解析RSS订阅源。基本的jQuery库能否直接完成此操作,还是需要使用插件?


1
我会选择 https://github.com/sdepold/jquery-rss —— 目前是最佳选择,有多个选项可用! :) - Komrath
对于从谷歌搜索进入此处的任何人,我必须为一个deviantART缩略图查看器创建类似的东西。漂亮简单且易于扩展:http://www.adamjamesnaylor.com/2012/11/05/Keratin-DeviantART-Latest-Deviation-Widget.aspx。请注意,它利用了谷歌的Feed阅读器,但仅用于将其转换为JSON格式。 - Adam Naylor
https://github.com/sdepold/jquery-rss - Blazemonger
20个回答

208

警告

Google Feed API已被官方弃用不再可用


不需要整个插件。这将把您的RSS作为JSON对象返回到回调函数:

function parseRSS(url, callback) {
  $.ajax({
    url: document.location.protocol + '//ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=10&callback=?&q=' + encodeURIComponent(url),
    dataType: 'json',
    success: function(data) {
      callback(data.responseData.feed);
    }
  });
}

4
尝试了 jFeed 但是没成功,这个方法可以很好地工作且不需要额外的库。 - diggersworld
16
注意,在使用Google API时,这些信息会被缓存,因此你可能无法获取到最新和最好的信息源。 - c0deNinja
3
它被缓存在哪里?我该如何清除缓存? - Jeg Bagus
41
这不是一个很好的答案。它依赖于第三方公司(Google)维护他们的服务。它没有回答原始问题(“使用jQuery解析RSS”),而是推广谷歌。如果谷歌放弃或修改他们的Ajax API,你的网站将会出现故障。 - Charles Goodwin
11
谷歌刚刚删除了这个API!https://developers.google.com/feed/?hl=en - GôTô
显示剩余7条评论

185
使用jFeed - 一个jQuery RSS/Atom插件。根据文档,它很简单:

使用 jFeed - 一个 jQuery RSS/Atom 插件。根据文档,它非常简单:

jQuery.getFeed({
   url: 'rss.xml',
   success: function(feed) {
      alert(feed.title);
   }
});

2
有现实世界使用的例子吗?例如解析和显示而不是警报。还是像$("#results").append(feed.title)这样简单? - Andy Brudtkuhl
3
注意:下载文件中有各种精彩的示例。 - Andy Brudtkuhl
12
或许你可以尝试使用7-zip?它是免费、开源的,能够打开多种文件类型,包括tar/gzip。 - Nathan Strutz
101
请注意,该插件的最新版本可在GitHub上获取:https://github.com/jfhovinne/jFeed。 - Alan H.
4
jFeed似乎已不再得到积极维护(最后一个更新记录已有2年之久,并且许多开放的拉取请求似乎被忽略),而且无法与最新版本的jQuery一起使用。 - Thilo
显示剩余3条评论

162

对于那些来参加讨论的人,从1.5版本开始,jQuery具有内置的XML解析功能,这使得在没有插件或第三方服务的情况下相当容易地完成此操作。它有一个parseXml函数,并且还会在使用$.get函数时自动解析XML。例如:

$.get(rssurl, function(data) {
    var $xml = $(data);
    $xml.find("item").each(function() {
        var $this = $(this),
            item = {
                title: $this.find("title").text(),
                link: $this.find("link").text(),
                description: $this.find("description").text(),
                pubDate: $this.find("pubDate").text(),
                author: $this.find("author").text()
        }
        //Do something with item here...
    });
});

10
XmlHttpRequest 错误:Origin 被 Access-Control-Allow-Origin 拒绝。 - jackocnr
12
是的,这种方法的缺点就在于此。如果您没有权限设置源服务器上的Access-Control-Allow-Origin头,则无法进行跨域请求。如果服务器支持jsonp,则这是您最好的选择。否则,您可以在您的域中使用代理脚本来检索xml,然后调用该脚本而不是外部服务器。 - David Hammond
这真的是唯一一个不依赖于外部插件或服务的答案吗? - Blazemonger
为什么 $this.find("link").text() 总是返回空字符串 ''? - Jeff Tian
@JeffTian,没有看到你的XML很难说。最明显的原因可能是缺少或为空的<link>元素。 - David Hammond
@DavidHammond,感谢您的回复。我发现问题的原因是返回的数据包含一些前导不可见空格,通过使用$ .parseXML(data)得知。所以我通过使用$xml = $($.parseXML(data.trim()));解决了这个问题,然后我可以按预期获取链接。 - Jeff Tian

16

更新(2019年10月15日)

我从jquery-rss中提取了核心逻辑,并创建了一个名为Vanilla RSS的新库,它使用fetch API并且可以在不需要任何其他依赖项的情况下运行:

const RSS = require('vanilla-rss');
const rss = new RSS(
    document.querySelector("#your-div"),
    "http://www.recruiter.com/feed/career.xml",
    { 
      // options go here
    }
);
rss.render().then(() => {
  console.log('Everything is loaded and rendered');
});

您还可以使用jquery-rss,它带有漂亮的模板,并且非常容易使用:

$("#your-div").rss("http://www.recruiter.com/feed/career.xml", {
    limit: 3,
    layoutTemplate: '<ul class="inline">{entries}</ul>',
    entryTemplate: '<li><a href="{url}">[{author}@{date}] {title}</a><br/>{shortBodyPlain}</li>'
})

收益率(截至2013年9月18日):

<div id="your-div">
    <ul class="inline">
    <entries></entries>
    </ul>
    <ul class="inline">
        <li><a href="http://www.recruiter.com/i/when-to-go-over-a-recruiter%e2%80%99s-head/">[@Tue, 10 Sep 2013 22:23:51 -0700] When to Go Over a Recruiter's Head</a><br>Job seekers tend to have a certain "fear" of recruiters and hiring managers, and I mean fear in the reverence and respect ...</li>
        <li><a href="http://www.recruiter.com/i/the-perfect-job/">[@Tue, 10 Sep 2013 14:52:40 -0700] The Perfect Job</a><br>Having long ago dealt with the "perfect resume" namely God's, in a previous article of mine, it makes sense to consider the ...</li>
        <li><a href="http://www.recruiter.com/i/unemployment-benefits-applications-remain-near-5-year-low-decline-again/">[@Mon, 09 Sep 2013 12:49:17 -0700] Unemployment Benefits Applications Remain Near 5-Year Low, Decline Again</a><br>As reported by the U.S. Department of Labor, the number of workers seeking unemployment benefits continued to sit near ...</li>
    </ul>
</div>

请查看http://jsfiddle.net/sdepold/ozq2dn9e/1/获取一个可用示例。


请注意,jquery-rss使用的是Google Feed API,该API会缓存提要(feed),这可能会导致问题。不过,您可以通过添加一个无用的URL参数来欺骗它:https://dev59.com/omrXa4cB1Zd3GeqPD-dI - kukabuka
请提供一个不使用 moment.js 的日期格式化示例。 - Purvesh Desai
请检查以下代码片段 https://gist.github.com/sdepold/d1e5e0e7a66fc77930fe它将生成类似于这样的内容: "<一些内容>,[@2015-11-18]" - sdepold
只是想提一下,jquery-rss并没有使用Google Feed API,而是使用了一个名为Feedr(https://github.com/sdepold/feedrapp)的替代工具,并且即使原始API被关闭,它仍然可以正常工作。 - sdepold
只是想提一下,使用Feedr时,jquery-rss对我返回了一个错误:“jquery-1.6.4.min.js:4 Mixed Content: The page at 'https://blah.com/' was loaded over HTTPS, but requested an insecure script 'http://www.feedrapp.info/etcetcetc'...”我尝试在脚本中强制使用“https:”,但它仍然会抛出错误。 - jimiayler
您愿意分享更多细节吗? 如果您启用SSL选项,这不应该发生。要完全复制,我需要:您如何将脚本包含在网站中,您如何使用脚本包含选项和目标RSS源。 - sdepold

16

jFeed在IE中无法正常工作。

使用zRSSFeed,可在5分钟内快速解决问题。


2
可在http://www.zazar.net/developers/zrssfeed/获取。 我打算自己试一下看看效果如何,看起来很有前途。 - thewinchester
3
顺便提一下,zRssFeed内部使用Google Feed RSS API。因此,如果想要自己进行HTML布局,直接查看API会更容易些。 - Ciantic
超酷的...唯一的问题是,如果他们能够在回调函数中提供 feed 对象而不是整个 HTML,那就太好了... - shahil
3
FYI,任何想要使用这个插件的人。开发者发布了以下内容。“此插件已停用由于谷歌Feeds API已被停止服务,而该插件依赖于此API,因此将不再提供或支持。”来源: http://www.zazar.net/developers/jquery/zrssfeed/ - phanf

15

使用JFeed

function getFeed(sender, uri) {
    jQuery.getFeed({
        url: 'proxy.php?url=' + uri,
        success: function(feed) {
            jQuery(sender).append('<h2>'
            + '<a href="'
            + feed.link
            + '">'
            + feed.title
            + '</a>'
            + '</h2>');

            var html = '';

            for(var i = 0; i < feed.items.length && i < 5; i++) {

                var item = feed.items[i];

                html += '<h3>'
                + '<a href="'
                + item.link
                + '">'
                + item.title
                + '</a>'
                + '</h3>';

                html += '<div class="updated">'
                + item.updated
                + '</div>';

                html += '<div>'
                + item.description
                + '</div>';
            }

            jQuery(sender).append(html);
        }    
    });
}

<div id="getanewbrowser">
  <script type="text/javascript">
    getFeed($("#getanewbrowser"), 'http://feeds.feedburner.com/getanewbrowser')
  </script>
</div>

9

1
这是一个好主意,但当你在需要使用对话框进行代理身份验证的防火墙内部时,它就无法工作了。 - thewinchester
1
Google Feed已被弃用,不再受支持。 - vikas etagi

8

更新 [2016年4月25日] 现在有更好的版本,具有更多选项和功能,托管在GitHub.jQRSS

我看到了被选中的答案,作者是Nathan Strutz,然而,jQuery插件页面链接仍然无法访问,该网站的主页似乎也没有加载。我尝试了其他几种解决方案,发现它们大多过时,而且非常简单!因此,我自己制作了一个插件,并且由于这里的链接已经失效,这似乎是提交答案的绝佳位置。如果您正在寻找这个答案2012年(即将进入2013年),您可能会像我一样注意到死链和旧建议所带来的挫败感。下面是我的现代插件示例链接以及插件代码!只需将代码复制到JS文件中并像任何其他插件一样在头部进行链接即可。使用极其容易!

jsFiddle

插件代码
2015年2月9日 - 长期以来更新检查console,在向其发送命令之前应该有所帮助!应该可以解决旧版IE的问题。

(function($) {
    if (!$.jQRSS) { 
        $.extend({  
            jQRSS: function(rss, options, func) {
                if (arguments.length <= 0) return false;

                var str, obj, fun;
                for (i=0;i<arguments.length;i++) {
                    switch(typeof arguments[i]) {
                        case "string":
                            str = arguments[i];
                            break;
                        case "object":
                            obj = arguments[i];
                            break;
                        case "function":
                            fun = arguments[i];
                            break;
                    }
                }

                if (str == null || str == "") {
                    if (!obj['rss']) return false;
                    if (obj.rss == null || obj.rss == "") return false;
                }

                var o = $.extend(true, {}, $.jQRSS.defaults);

                if (typeof obj == "object") {
                    if ($.jQRSS.methods.getObjLength(obj) > 0) {
                        o = $.extend(true, o, obj);
                    }
                }

                if (str != "" && !o.rss) o.rss = str;
                o.rss = escape(o.rss);

                var gURL = $.jQRSS.props.gURL 
                    + $.jQRSS.props.type 
                    + "?v=" + $.jQRSS.props.ver
                    + "&q=" + o.rss
                    + "&callback=" + $.jQRSS.props.callback;

                var ajaxData = {
                        num: o.count,
                        output: o.output,
                    };

                if (o.historical) ajaxData.scoring = $.jQRSS.props.scoring;
                if (o.userip != null) ajaxData.scoring = o.userip;

                $.ajax({
                    url: gURL,
                    beforeSend: function (jqXHR, settings) { if (window['console']) { console.log(new Array(30).join('-'), "REQUESTING RSS XML", new Array(30).join('-')); console.log({ ajaxData: ajaxData, ajaxRequest: settings.url, jqXHR: jqXHR, settings: settings, options: o }); console.log(new Array(80).join('-')); } },
                    dataType: o.output != "xml" ? "json" : "xml",
                    data: ajaxData,
                    type: "GET",
                    xhrFields: { withCredentials: true },
                    error: function (jqXHR, textStatus, errorThrown) { return new Array("ERROR", { jqXHR: jqXHR, textStatus: textStatus, errorThrown: errorThrown } ); },
                    success: function (data, textStatus, jqXHR) {  
                        var f = data['responseData'] ? data.responseData['feed'] ? data.responseData.feed : null : null,
                            e = data['responseData'] ? data.responseData['feed'] ? data.responseData.feed['entries'] ? data.responseData.feed.entries : null : null : null
                        if (window['console']) {
                            console.log(new Array(30).join('-'), "SUCCESS", new Array(30).join('-'));
                            console.log({ data: data, textStatus: textStatus, jqXHR: jqXHR, feed: f, entries: e });
                            console.log(new Array(70).join('-'));
                        }

                        if (fun) {
                            return fun.call(this, data['responseData'] ? data.responseData['feed'] ? data.responseData.feed : data.responseData : null);
                        }
                        else {
                            return { data: data, textStatus: textStatus, jqXHR: jqXHR, feed: f, entries: e };
                        }
                    }
                });
            }
        });
        $.jQRSS.props = {
            callback: "?",
            gURL: "http://ajax.googleapis.com/ajax/services/feed/",
            scoring: "h",
            type: "load",
            ver: "1.0"
        };
        $.jQRSS.methods = {
            getObjLength: function(obj) {
                if (typeof obj != "object") return -1;
                var objLength = 0;
                $.each(obj, function(k, v) { objLength++; })
                return objLength;
            }
        };
        $.jQRSS.defaults = {
            count: "10", // max 100, -1 defaults 100
            historical: false,
            output: "json", // json, json_xml, xml
            rss: null,  //  url OR search term like "Official Google Blog"
            userip: null
        };
    }
})(jQuery);

用途

//  Param ORDER does not matter, however, you must have a link and a callback function
//  link can be passed as "rss" in options
//  $.jQRSS(linkORsearchString, callbackFunction, { options })

$.jQRSS('someUrl.xml', function(feed) { /* do work */ })

$.jQRSS(function(feed) { /* do work */ }, 'someUrl.xml', { count: 20 })

$.jQRSS('someUrl.xml', function(feed) { /* do work */ }, { count: 20 })

$.jQRSS({ count: 20, rss: 'someLink.xml' }, function(feed) { /* do work */ })

$.jQRSS('在此处输入搜索关键字而非链接', function(feed) { /* 处理函数 */ }) // TODO: 需要修复

选项

{
    count: // default is 10; max is 100. Setting to -1 defaults to 100
    historical: // default is false; a value of true instructs the system to return any additional historical entries that it might have in its cache. 
    output: // default is "json"; "json_xml" retuns json object with xmlString / "xml" returns the XML as String
    rss: // simply an alternate place to put news feed link or search terms
    userip: // as this uses Google API, I'll simply insert there comment on this:
        /*  Reference: https://developers.google.com/feed/v1/jsondevguide
            This argument supplies the IP address of the end-user on 
            whose behalf the request is being made. Google is less 
            likely to mistake requests for abuse when they include 
            userip. In choosing to utilize this parameter, please be 
            sure that you're in compliance with any local laws, 
            including any laws relating to disclosure of personal 
            information being sent.
        */
}

5
(function(url, callback) {
    jQuery.ajax({
        url: document.location.protocol + '//ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=10&callback=?&q=' + encodeURIComponent(url),
        dataType: 'json',
        success: function(data) {
            callback(data.responseData.feed);
        }
    });
})('http://news.hitb.org/rss.xml', function(feed){ // Change to desired URL
    var entries = feed.entries, feedList = '';
    for (var i = 0; i < entries.length; i++) {
        feedList +='<li><a href="' + entries[i].link + '">' + entries[i].title + '</a></li>';
    }
    jQuery('.feed > ul').append(feedList);
});


<div class="feed">
        <h4>Hacker News</h4>
        <ul></ul>
</div>

5

我同意@Andrew的观点,使用Google是一种可靠、可重复使用的方法,它有一个巨大的优势,就是你可以获得JSON而不是XML。使用Google作为代理的另一个优点是,可能会阻止您直接访问其数据的服务,不太可能停止Google。以下是使用滑雪报告和条件数据的示例。这具有所有常见的实际应用程序:1)第三方RSS/XML 2)JSONP 3)在无法完全按照您想要的方式获取数据时,清理字符串和将字符串转换为数组4)在加载时将元素添加到DOM。希望这对一些人有所帮助!

<!-- Load RSS Through Google as JSON using jQuery -->
<script type="text/javascript">

    function displaySkiReport (feedResponse) {

    // Get ski report content strings
    var itemString = feedResponse.entries[0].content;
    var publishedDate = feedResponse.entries[0].publishedDate;

    // Clean up strings manually as needed
    itemString = itemString.replace("Primary: N/A", "Early Season Conditions"); 
    publishedDate = publishedDate.substring(0,17);

    // Parse ski report data from string
    var itemsArray = itemString.split("/");


    //Build Unordered List
    var html = '<h2>' + feedResponse.entries[0].title + '</h2>';
    html += '<ul>';

    html += '<li>Skiing Status: ' + itemsArray[0] + '</li>';
    // Last 48 Hours
    html += '<li>' + itemsArray[1] + '</li>';
    // Snow condition
    html += '<li>' + itemsArray[2] + '</li>';
    // Base depth
    html += '<li>' + itemsArray[3] + '</li>';

    html += '<li>Ski Report Date: ' + publishedDate + '</li>';

    html += '</ul>';

    $('body').append(html);    

    }


    function parseRSS(url, callback) {
      $.ajax({
    url: document.location.protocol + '//ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=10&callback=?&q=' + encodeURIComponent(url),
    dataType: 'json',
    success: function(data) {
      callback(data.responseData.feed);
    }
      });
    }

    $(document).ready(function() {              

        // Ski report
        parseRSS("http://www.onthesnow.com/michigan/boyne-highlands/snow.rss", displaySkiReport);

    });

</script>

2
这不会起作用,因为存在跨域问题。你需要使用JSONP。 - gotofritz
1
它对我有效。你测试过吗?相当确定谷歌使用回调参数而不是ajax dataType返回jsonp。 - Dylan Valade
不确定为什么会被点踩。这段代码三年后仍然有效。将其全部粘贴到控制台,您将看到当前(XML)滑雪条件添加到此页面的页脚。 - Dylan Valade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接