我想在google app engine / python下提供RSS Feed。
我尝试使用通常的请求处理程序并生成xml响应。当我直接访问Feed网址时,我可以正确看到Feed,但是,当我尝试在Google阅读器中订阅Feed时,它会说
'无法找到所请求的Feed。'
我想知道这种做法是否正确。我正在考虑使用静态xml文件并通过cron作业更新它。但是虽然GAE不支持文件i / o,但这种方法似乎不起作用。
如何解决这个问题?谢谢!
答案 0 :(得分:6)
我建议有两种解决方案:
GAE-REST您可以添加到您的项目并进行配置,它将为您制作RSS,但项目已经过时,不再维护。
像我一样,使用模板写一个列表并且像这样我可以成功生成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)
我希望其中一些适合你,两种方式都适合我。
答案 1 :(得分:2)
我的博客上有一个Atom feed生成器,可以在AppEngine / Python上运行。我使用Django 1.2模板引擎来构建feed。我的模板如下所示:
<?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格式更新Feed内容的时间和日期。幸运的是,Python有一个库来为您处理这个问题。生成Feed的控制器的摘录:
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
据我所知,这就是所需要的,而且这段代码确实为我的博客生成了一个非常好的工作Feed。现在,如果您真的想要使用RSS而不是Atom,则需要更改Feed模板,Post模板和content_type的格式,但我认为这是获取Feed所需要做的事情的本质从AppEngine / Python应用程序生成。
答案 2 :(得分:2)
与HTML相比,生成XML没有什么特别之处 - 前提是您正确设置了内容类型。将您的Feed传递给http://validator.w3.org/feed/处的验证器,它会告诉您它有什么问题。
如果这没有帮助,您需要向我们展示您的来源 - 如果您不向我们展示,我们无法为您调试代码。