1

在我当前的应用程序中,我使用 TornadoAsyncHttpClient向网站发出请求。流程很复杂,处理来自先前请求的响应会导致另一个请求。

实际上,我下载了一篇文章,然后对其进行分析并下载其中提到的图片

困扰我的是,虽然在我的日志中我清楚地看到消息表明.fetch()已发出照片 URL,但没有发出实际的 HTTP 请求,正如在Wireshark中嗅探的那样

我尝试修改 max_client_count 和 Curl/Simple HTTP 客户端,但 bahvior 总是相同的 - 直到所有文章都被下载,而不是实际发出照片请求。怎么能改变呢?

更新。一些伪代码

@VictorSergienko我在Linux上,所以默认情况下,我猜,使用EPoll版本。整个系统过于复杂,但归结为:

@gen.coroutine
def fetch_and_process(self, url, callback):
  body = yield self.async_client.fetch(url)
  res = yield callback(body)
  return res

@gen.coroutine
def process_articles(self,urls):
  wait_ids=[]
  for url in urls:
     #Enqueue but don't wait for one
     IOLoop.current().add_callback(self.fetch_and_process(url, self.process_article))
     wait_ids.append(yield gen.Callback(key=url))
  #wait for all tasks to finish
  yield wait_ids

@gen.coroutine
def process_article(self,body):
   photo_url=self.extract_photo_url_from_page(body)
   do_some_stuff()
   print('I gonna download that photo '+photo_url)
   yield self.download_photo(photo_url)

@gen.coroutine
def download_photo(self, photo_url):
  body = yield self.async_client.fetch(photo_url)
  with open(self.construct_filename(photo_url)) as f:
   f.write(body)

当它打印出来时,我会下载那张照片,没有实际的请求!相反,它会继续下载更多文章并将更多照片排入队列,直到下载所有文章,然后才批量请求所有照片

4

1 回答 1

1

AsyncHTTPClient 有一个队列,您将立即在 process_articles 中填充该队列(“入队但不要等待一个”)。在处理第一篇文章时,其照片将排在所有其他文章之后的队列末尾。

如果您yield self.fetch_and_process在 process_articles 中使用 add_callback 而不是 add_callback,您将在文章和他们的照片之间交替,但您一次只能下载一个内容。为了保持文章和照片之间的平衡,同时仍然一次下载多个内容,请考虑将toro包用于同步原语。http://toro.readthedocs.org/en/stable/examples/web_spider_example.html中的示例与您的用例类似。

于 2014-12-15T22:09:54.277 回答