【问题标题】:Generating RSS feed under Google App Engine在 Google App Engine 下生成 RSS 提要
【发布时间】:2011-12-14 15:41:54
【问题描述】:

我想在 google app engine/python 下提供 rss feed。

我尝试使用通常的请求处理程序并生成 xml 响应。当我直接访问提要网址时,我可以正确地看到提要,但是,当我尝试在谷歌阅读器中订阅提要时,它会说

'找不到请求的提要。'

我想知道这种方法是否正确。我正在考虑使用静态 xml 文件并通过 cron 作业对其进行更新。但是虽然 GAE 不支持文件 i/o,但这种方法似乎行不通。

如何解决这个问题?谢谢!

【问题讨论】:

  • 我的猜测是您可能需要在响应标头中设置正确的内容类型,以便浏览器将其识别为 rss 提要。但我现在懒得查内容类型是什么,给你一个正式的答案。

标签: python google-app-engine rss


【解决方案1】:

我建议有 2 个解决方案:

  1. GAE-REST您可以添加到您的项目并进行配置,它会为您生成 RSS,但该项目已旧且不再维护。

  2. 像我一样,使用模板写入列表,这样我可以成功生成可以通过谷歌阅读器读取的 RSS (GeoRSS),其中模板是:

    <title>{{host}}</title>
    <link href="http://{{host}}" rel="self"/>
    <id>http://{{host}}/</id>
    <updated>2011-09-17T08:14:49.875423Z</updated>
    <generator uri="http://{{host}}/">{{host}}</generator>
    
    {% for entity in entities %}
    
    <entry>
    
    <title><![CDATA[{{entity.title}}]]></title>
    <link href="http://{{host}}/vi/{{entity.key.id}}"/>
    <id>http://{{host}}/vi/{{entity.key.id}}</id>
    <updated>{{entity.modified.isoformat}}Z</updated>
    <author><name>{{entity.title|escape}}</name></author>
    <georss:point>{{entity.geopt.lon|floatformat:2}},{{entity.geopt.lat|floatformat:2}}</georss:point>
    <published>{{entity.added}}</published>
    <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml">{{entity.text|escape}}</div>
    </summary>
    
    </entry>
    
    {% endfor %}
    
    </feed>
    

我的处理程序是(您也可以将 python 2.7 用作处理程序外部的一个函数,以获得更简单的解决方案):

class GeoRSS(webapp2.RequestHandler):

    def get(self):
        start = datetime.datetime.now() - timedelta(days=60)
        count = (int(self.request.get('count'
                 )) if not self.request.get('count') == '' else 1000)
        try:
            entities = memcache.get('entities')
        except KeyError:
            entity = Entity.all().filter('modified >',
                                  start).filter('published =',
                    True).order('-modified').fetch(count)
        memcache.set('entities', entities)
        template_values = {'entities': entities, 'request': self.request,
                           'host': os.environ.get('HTTP_HOST',
                           os.environ['SERVER_NAME'])}
        dispatch = 'templates/georss.html'
        path = os.path.join(os.path.dirname(__file__), dispatch)
        output = template.render(path, template_values)
        self.response.headers['Cache-Control'] = 'public,max-age=%s' \
            % 86400
        self.response.headers['Content-Type'] = 'application/rss+xml'
        self.response.out.write(output)

我希望其中一些对你有用,两种方式都对我有用。

【讨论】:

    【解决方案2】:

    我的博客有一个 Atom 提要生成器,它在 AppEngine/Python 上运行。我使用 Django 1.2 模板引擎来构建提要。我的模板如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <feed xmlns="http://www.w3.org/2005/Atom"
          xml:lang="en"
          xml:base="http://www.example.org">
      <id>urn:uuid:4FC292A4-C69C-4126-A9E5-4C65B6566E05</id>
      <title>Adam Crossland's Blog</title>
      <subtitle>opinions and rants on software and...things</subtitle>
      <updated>{{ updated }}</updated>
      <author>
        <name>Adam Crossland</name>
        <email>adam@adamcrossland.net</email>
      </author>
      <link href="http://blog.adamcrossland.net/" />
      <link rel="self" href="http://blog.adamcrossland.net/home/feed" />
      {% for each_post in posts %}{{ each_post.to_atom|safe }}
      {% endfor %}
    </feed>
    

    注意:如果您使用其中任何一个,您需要创建自己的 uuid 才能进入 id 节点。

    更新的节点应包含提要内容最后更新为rfc 3339 格式的时间和日期。幸运的是,Python 有一个库可以为您解决这个问题。生成提要的控制器的摘录:

        from rfc3339 import rfc3339
    
        posts = Post.get_all_posts()
        self.context['posts'] = posts
    
        # Initially, we'll assume that there are no posts in the blog and provide
        # an empty date.
        self.context['updated'] = ""
    
        if posts is not None and len(posts) > 0:
            # But there are posts, so we will pick the most recent one to get a good
            # value for updated.
            self.context['updated'] = rfc3339(posts[0].updated(), utc=True)
    
        response.content_type = "application/atom+xml"
    

    不要担心self.context['updated'] 的东西。这就是我的框架如何提供设置模板变量的快捷方式。导入部分是我使用rfc3339 函数对我想使用的日期进行编码。另外,我将 Response 对象的content_type 属性设置为application/atom+xml

    唯一缺少的部分是模板使用了一个名为to_atom 的方法将Post 对象转换为Atom 格式的数据:

    def to_atom(self):
        "Create an ATOM entry block to represent this Post."
    
        from rfc3339 import rfc3339
    
        url_for = self.url_for()
        atom_out = "<entry>\n\t<title>%s</title>\n\t<link href=\"http://blog.adamcrossland.net/%s\" />\n\t<id>%s</id>\n\t<summary>%s</summary>\n\t<updated>%s</updated>\n  </entry>" % (self.title, url_for, self.slug_text, self.summary_for(), rfc3339(self.updated(), utc=True))
    
        return atom_out
    

    据我所知,这就是所需的全部内容,并且此代码确实为我的博客生成了一个完美且有效的提要。现在,如果你真的想做 RSS 而不是 Atom,你需要改变 feed 模板、Post 模板和 content_type 的格式,但我认为这是获取 feed 所需要做的事情的本质从 AppEngine/Python 应用程序生成。

    【讨论】:

    • 谢谢!这很有帮助!
    【解决方案3】:

    与 HTML 相比,生成 XML 并没有什么特别之处 - 只要您正确设置了内容类型。将您的提要通过http://validator.w3.org/feed/ 传递给验证器,它会告诉您它有什么问题。

    如果这没有帮助,您需要向我们展示您的源代码 - 如果您不向我们展示代码,我们将无法为您调试代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-05
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 2013-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多