0

我有一个要从中提取数据的 API,我想从该 API 收集所有标签...但我不知道标签的数量,并且 API 通过返回的最大结果数限制访问在任何 1 个电话 (100) 中。虽然它有无限数量的页面。

所以一个调用可能看起来像这样:Tag.update_tags(100, 5)哪里100是 1 次调用中返回的最大对象数,5是要开始的页面(即,如果您假设标签是按顺序存储的,这就是说返回带有 ID 的标签记录的范围401 - 500

问题是,我不想手动输入5(即我不知道上限是多少)。我无法 ping 标签的总数(如果有,我会简单地将它分开并将这个调用放在一个循环中,直到那个数字)。

我所知道的是,一旦它到达一个没有任何结果的页面,它将返回一个空数组[]

那么,如何循环遍历所有标签并在返回的结果为空数组时停止(这将是返回的最终结果,因此未评估)?

那个循环是什么样子的?

4

2 回答 2

1

当结果返回空数组时,使用带有 break 语句的无条件循环。

i = 1
loop do
  result = call_to_api(i)
  do_something_with(result)
  i += 1
  break if result.empty?
end

当然,在生产场景中,您需要一些更健壮的东西,包括异常处理程序、一些进度日志报告和某种具体的迭代限制,以确保循环不会变得无限。

更新

这是一个使用类来包装逻辑的示例。

class Api
  DEFAULT_OPTIONS = {:start_position => 1, :max_iterations => 1000}

  def initialize(base_uri, config)
    @config = DEFAULT_OPTIONS.merge(config)
    @position = config[:start_position]
    @results_count = 0
  end

  def each(&block)
    advance(&block) while can_advance?
    log("Processed #{@results_count} results")
  end

  def advance(&block)
    yield result
    @results_count += result.count
    @position += 1
    @current_result = nil
  end

  def result
    @current_result ||= begin
      response = Net::HTTP.get_response(current_uri)
      JSON.decode(response.body)
    rescue
      # provide some exception handling/logging
    end
  end

  def can_advance?
    @position < (@config[:start_position] + @config[:max_iterations]) && result.any?
  end

  def current_uri
    Uri.parse("#{@base_uri}?page=#{@position}")
  end
end

api = Api.new('http://somesite.com/api/v1/resource')

api.each do |result|
  do_something_with(result)
end

通过为每个线程设置启动和迭代计数,这也有一个角度允许并发,这将通过并发 http 请求明确地加快这一速度。

于 2013-02-22T23:45:08.800 回答
0

嗯。您一次可以获得 100 个项目,并从特定页面开始。如何实现迭代取决于您想要做什么。假设您要收集所有唯一标签。建立一个映射(例如,一个HashMap),然后一次检索一页并处理它。当你点击一个空的页面时,你就完成了。

// Implements a map and methods to update it
MyHashMap uniqueTags;
// Stores a page of tags
Page page;
Do
    // get a page of tags
    page = readTags();
    if (page != null) {
        uniqueTags.getUniqueTags(page);
    } else {
        break;
    }
until (page == null);
于 2013-02-22T23:08:11.993 回答