1

我正在尝试做一个非常简单的 Python 网络服务。它使用 Flickr API 创建一个“photo.search”并返回标题和照片的 URL。

该网络服务将托管在 Google App Engine 上。

这就是我现在真正拥有的:

import webapp2
from urllib import urlencode, urlopen
from xml.dom import minidom
from google.appengine.api import urlfetch

class MainPage(webapp2.RequestHandler):

  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'

    data = _doget('flickr.photos.search', text='to_search', per_page='2')
    self.response.write('Ok')

  def _prepare_params(params):
    for (key, value) in params.items():
        if isinstance(value, list):
            params[key] = ','.join([item for item in value])
    return params

  def _doget(method, auth=False, **params):

    params = _prepare_params(params)
    url = 'http://flickr.com/services/rest/?api_key=%s&method=%s&%s%s'% \
          ('stackoverflow_key', method, urlencode(params),
                  _get_auth_url_suffix(method, auth, params))

    result = urlfetch.fetch(url)
    minidom.parse(result.content)
    return result

application = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

我是 Python 的初学者,所以如果我犯了大错,我深表歉意 :) 我尝试了几个不起作用的教程和示例代码。

导入导致 500 服务器错误

Error: Server Error

The server encountered an error and could not complete your request.
If the problem persists, please report your problem and mention this error message and the query that caused it.

有谁可以告诉我它有什么问题?

如果有人有可以解决问题的示例代码,那就太好了。

非常感谢您的宝贵时间!!:D

编辑 :

好吧,我改变了我的代码,它比以前更简单,用于测试:

import webapp2
from urllib import urlencode, urlopen
from xml.dom import minidom
from google.appengine.ext.webapp.util import run_wsgi_app
import hashlib
import os


HOST = 'http://api.flickr.com'
API = '/services/rest'
API_KEY = 'my_key'


class MainPage(webapp2.RequestHandler):

     def get(self):
        self.response.headers['Content-Type'] = 'text/html'

        data = _doget('flickr.photos.search', auth=False, text='to_search', per_page='1')
        if data:
           self.response.write(data)
        else:
            self.response.write('Error')

 def _doget(method, **params):

    url = '%s%s/?api_key=%s&method=%s&%s&format=json'% \
      (HOST, API, API_KEY, method, urlencode(params))

    res = urlfetch.fetch(url).content

    # Flickr JSON api returns not valid JSON, which wrapped with "jsonFlickrApi(...)", so we get rid of it.
    if 'jsonFlickrApi(' in res:
        return res[14:-1]

    return json.loads(res)

application = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

当我复制/粘贴此网址时,它可以完美运行。我的目标是在 flickr 返回数据时返回数据。但仍然无法正常工作。甚至没有显示打印:(

4

2 回答 2

1

从哪里_get_data进口?

附带说明一下,appengine 带有一个 urlfetch 服务,我建议您使用它,除非您有充分的理由不这样做。请参阅:https ://developers.google.com/appengine/docs/python/urlfetch/

在使用中,这看起来像:

from google.appengine.api import urlfetch

result = urlfetch.fetch(url=url)
if result.status_code == 200:
    minidom.parse(result.content)
于 2013-10-13T14:23:18.207 回答
1

乍一看,您的应用程序有几个问题:

  1. 我想 HOST 应该是' http://api.flickr.com '
  2. MainPage 类中 if-else 语句中的缩进和格式化(:在 if 和 else 之后)
  3. self.response.write(photos) 中未定义的变量“照片”
  4. _doget 函数中未定义的函数“_prepare_params”、“_get_auth_url_suffix”、“_get_data”和变量“debug”。
  5. 您应该调用 urlopen 结果的 read() 方法
  6. 你应该使用 minidom.parseString
  7. 您可以使用 run_wsgi_app 来运行您的应用程序

所以这是一个工作示例:

from google.appengine.ext.webapp.util import run_wsgi_app
import webapp2
from urllib import urlencode, urlopen
from xml.dom import minidom
import hashlib
import os

HOST = 'http://api.flickr.com'
API = '/services/rest'
API_KEY = 'my_key'

debug = False

class MainPage(webapp2.RequestHandler):

    def get(self):
        self.response.headers['Content-Type'] = 'text/html'

        data = _doget('flickr.photos.search', auth=False, text='boston', per_page='2')

        if data:
            photos = data.getElementsByTagName("photo")
            for photo in photos:
                farm_id = 1 # ???
                server_id = photo.attributes['server'].value
                photo_id = photo.attributes['id'].value
                secret = photo.attributes['secret'].value
                photo_url = 'http://farm{farm_id}.staticflickr.com/{server_id}/{photo_id}_{secret}.jpg'.format(farm_id=farm_id,                                                                                                         server_id=server_id,                                                                                                         photo_id=photo_id,                                                                                                         secret=secret)
                self.response.write('<img src="{0}">'.format(photo_url))
        else:
            self.response.write('Error')


def _doget(method, auth=False, **params):
    #print "***** do get %s" % method

    params = params
    url = '%s%s/?api_key=%s&method=%s&%s'% \
      (HOST, API, API_KEY, method, urlencode(params))

    #another useful debug print statement
    if debug:
        print "_doget", url

    res = urlopen(url)
    res = res.read()

    return minidom.parseString(res)


application = webapp2.WSGIApplication([('/', MainPage),], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

为了格式化 flickr 照片 url,我使用了http://www.flickr.com/services/api/misc.urls.html,但我还没有找到从哪里获取 farm_id 参数,希望你自己管理)


此外,通过将 'format=json' 传递给 API 请求 URL 可以更容易地使用 json 格式,并且更正确地使用 GAE urlfetch 服务:

import json
from google.appengine.api import urlfetch

# ...

class MainPage(webapp2.RequestHandler):
    def get(self):
        # ...
        for photo in data['photos']['photo']:
            farm_id = 1 # ???
            server_id = photo['server']
            photo_id = photo['id']
            secret = photo['secret']
            # ...

def _doget(method, auth=False, **params):
    # ...
    url = '%s%s/?api_key=%s&method=%s&%s&format=json'% \
      (HOST, API, API_KEY, method, urlencode(params))

    res = urlfetch.fetch(url).content

    # Flickr JSON api returns not valid JSON, which wrapped with "jsonFlickrApi(...)", so we get rid of it.
    if 'jsonFlickrApi(' in res:
        return res[14:-1]

    return json.loads(res)
于 2013-10-13T15:19:21.050 回答