GAE - 如何组合几个异步URL提取的结果?

时间:2013-02-18 19:59:32

标签: python google-app-engine urlfetch

我有一个Google AppEngine(在Python)应用程序中,我需要执行4到5次网址提取,然后在将数据打印到响应之前合并数据。

我可以使用同步工作流程毫无问题地执行此操作,但由于我提取的网址彼此不相关或相互依赖,因此异步执行此操作将是最理想的(也是最快的)。

我已阅读并重新阅读文档here,但我无法弄清楚如何阅读每个网址的内容。我也在网上搜索了一个小例子(这正是我真正需要的)。我已经看到了this SO问题,但是在这里他们没有提到任何关于阅读这些单独的异步URL提取内容的内容。

有没有人有任何关于如何使用AppEngine执行4或5个异步URL提取的简单示例?然后在将结果打印到响应之前合并结果?

这是我到目前为止所做的:

rpcs = []
for album in result_object['data']:
  total_facebook_photo_count = total_facebook_photo_count + album['count']
  facebook_albumid_array.append(album['id'])

  #Get the photos in the photo album
  facebook_photos_url = 'https://graph.facebook.com/%s/photos?access_token=%s&limit=1000' % (album['id'], access_token)

  rpc = urlfetch.create_rpc()
  urlfetch.make_fetch_call(rpc, facebook_photos_url)
  rpcs.append(rpc)

for rpc in rpcs:
  result = rpc.get_result()
  self.response.out.write(result.content)

但是,它仍然看起来像行:result = rpc.get_result()强制它等待第一个请求完成,然后是第二个,然后是第三个,依此类推。有没有办法简单地将结果放入收到的变量中?

谢谢!

2 个答案:

答案 0 :(得分:2)

example中,text = result.content是您获取内容(正文)的地方。

要在并行中进行网址提取,您可以设置它们,添加到列表中并在之后检查结果。扩展已经提到的示例,它可能看起来像:

from google.appengine.api import urlfetch

futures = []
for url in urls:
    rpc = urlfetch.create_rpc()
    urlfetch.make_fetch_call(rpc, url)
    futures.append(rpc)

contents = []
for rpc in futures:
    try:
        result = rpc.get_result()
        if result.status_code == 200:
            contents.append(result.content)
            # ...
    except urlfetch.DownloadError:
        # Request timed out or failed.
        # ...

concatenated_result = '\n'.join(contents)

在这个例子中,我们组装了返回状态代码200的所有请求的主体,并连接它们之间的换行符。

或者使用ndb,我个人偏好GAE上的任何异步,例如:

@ndb.tasklet
def get_urls(urls):
  ctx = ndb.get_context()
  result = yield map(ctx.urlfetch, urls)
  contents = [r.content for r in result if r.status_code==200]
  raise ndb.Return('\n'.join(contents))

答案 1 :(得分:1)

我使用此代码(在了解ndb tasklets 之前已实现):

    while rpcs:
      rpc = UserRPC.wait_any(rpcs)
      result = rpc.get_result()
      # process result here
      rpcs.remove(rpc)