【问题标题】:Python requests arguments/dealing with api paginationPython请求参数/处理api分页
【发布时间】:2013-07-20 14:43:37
【问题描述】:

我正在使用 Angel List (AL) API,并希望获得旧金山的所有工作。 由于我找不到用于 api 的活动 Python 包装器(如果我取得任何进展,我想我想自己制作),我正在使用 requests 库。

AL API 的结果是分页的,我不知道如何超出结果的第一页。

这是我的代码:

import requests
r_sanfran = requests.get("https://api.angel.co/1/tags/1664/jobs").json()
r_sanfran.keys()
# returns [u'per_page', u'last_page', u'total', u'jobs', u'page']
r_sanfran['last_page']
#returns 16
r_sanfran['page']
# returns 1

我尝试向requests.get 添加参数,但没有奏效。我还尝试了一些非常愚蠢的方法——改变'page'键的值就像神奇地为我分页一样。

例如。 r_sanfran['page'] = 2

我猜这是相对简单的事情,但我似乎无法弄清楚,所以任何帮助都会很棒。

一如既往的感谢。

Angel List API documentation如果有帮助的话。

【问题讨论】:

  • 作为参考,this answer 分享了一些关于如何进行 API 分页的通用方法。

标签: python api http pagination python-requests


【解决方案1】:

改进@alecxe 的回答:如果您使用 Python 生成器和请求 HTTP 会话,如果您查询大量页面或非常大的页面,则可以提高性能和资源使用率。

import requests

session = requests.Session()

def get_jobs():
    url = "https://api.angel.co/1/tags/1664/jobs" 
    first_page = session.get(url).json()
    yield first_page
    num_pages = first_page['last_page']

    for page in range(2, num_pages + 1):
        next_page = session.get(url, params={'page': page}).json()
        yield next_page

for page in get_jobs():
    # TODO: process the page

【讨论】:

  • 这太棒了。我可以通过一个小的修改来使用它来导航一个使用 LimitOffsetPagination 的 drf api
  • 不是更好,但是当还需要提供页面大小作为参数时,比如params={"page": 1, "page_size": 25},那么可以定义一次完整的params,然后直接分配给params["page"],例如: for params["page"] in range(2, ...)session.get(url, params=params) ?
【解决方案2】:

阅读last_page并为范围内的每个页面发出获取请求:

import requests

r_sanfran = requests.get("https://api.angel.co/1/tags/1664/jobs").json()
num_pages = r_sanfran['last_page']

for page in range(2, num_pages + 1):
    r_sanfran = requests.get("https://api.angel.co/1/tags/1664/jobs", params={'page': page}).json()
    print r_sanfran['page']
    # TODO: extract the data

【讨论】:

  • 我猜应该是range(2, num_pages + 1),因为第一页是 1,而 16 是总页数,所以希望将其包含在范围内......(并且可能想要使用requests.get('http://...blah...?', params={'page': page}) 避免字符串插值
  • 啊。我没有看到我可以在 requests.get 中传递 params 参数
  • 啊。好的。我明白发生了什么。我以为分页来自 angel.co/1...angel.co/2 等。感谢您的帮助!
  • 在 params={ 之后缺少结束 '}'
  • @API_sheriff_orlie 是的,已修复,非常感谢您从完美主义者到完美主义者 :)
【解决方案3】:

我遇到了 API 不返回页面而是返回最小值/最大值的场景。我创建了这个,我认为它适用于这两种情况。这会自动增加增量,直到它到达末尾,然后它会停止 while 循环。

max_version = [1]
while len(max_version) > 0:
    r = requests.get(url, headers=headers, params={"page": max_version[0]}).json()
    next_page = r['page']
    if next_page is not None:
        max_version[0] = next_page
        Process data...
    else:
        max_version.clear() # Stop the while loop

【讨论】:

    【解决方案4】:

    进一步改进 @dh762 的答案,您可以使用 while 并在其中完成所有请求,而无需 2 个 yield 语句。

    例如:

    import requests
    
    session = requests.Session()
    
    def get_jobs():
        url = "https://api.angel.co/1/tags/1664/jobs"
        currP = 1
        totalP = 2 #assuming there's gonna be 2nd page, it'll get overwritten if not.
        while (currP <= totalP):
            page = session.get(url, params={'page': currP}).json()
            totalP = page['last_page']
            currP += 1
            yield page
    
    for page in get_jobs():
        # TODO: process the page
    

    【讨论】:

      【解决方案5】:

      这对我有用,使用**extraArgs

      # our initial url
      url = f'{base_url}/{api_endpoint}'
      
      # we set a next token, to start our while loop
      NextToken = True
      
      # we specify our extra args object
      extraArgs = {
          "url": url,
          "headers": headers
      }
      
      while NextToken is not None:
          # call api
          r = requests.get(**extraArgs)
          result = r.json()
      
          # if next url exists, add to method arguments, and do next call with it
          if 'next' in result['_links']:
              next_link = result['_links']['next']['href']
              print(f'found next link: {next_link}')
              extraArgs['url'] = next_link
          else:
              break
      
      

      【讨论】:

        【解决方案6】:

        我的页面在 Python 中运行,但我不确定是否会出现类似的情况,因为我使用的是加密 API:

        pages=3
        fl=client.get_fills(ord['product_id'])#fl equals paginated message requested
        fil=list(fl)
        #you can skip that last 2 lines with: fil=list(client.get_fills(ord['product_id']))
        #they're just for clarification
        print(json.dumps(fil[0:pages], indent=2, sort_keys=True))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-10-21
          • 2023-02-09
          • 2017-09-10
          • 1970-01-01
          • 2014-09-10
          • 1970-01-01
          • 2014-12-03
          相关资源
          最近更新 更多