如何从跨多个页面的 GET 请求中提取所有结果?
Posted
技术标签:
【中文标题】如何从跨多个页面的 GET 请求中提取所有结果?【英文标题】:How do I extract all results from a GET request that spans multiple pages? 【发布时间】:2021-10-07 20:24:56 【问题描述】:我已经成功编写了调用 API 并将结果转换为 DataFrame 的代码。
wax_wallet = "zqsfm.wam"
# Get Assets from AtomicHub API
response1 = requests.get(
"https://wax.api.atomicassets.io/atomicassets/v1/assets?"
f"owner=wax_wallet"
"&collection_whitelist=nftdraft2121"
"&page=1"
"&limit=1000"
"&order=asc"
"&sort=name")
# Save Response as JSON
json_assets = response1.json()
# Convert JSON to DataFrame
df = pd.json_normalize(json_assets['data'])
此 API 每页最多返回 1000 个项目,因此我需要让它循环遍历所需的多个页面,并最终将结果存储到 DataFrame 中。
我试图用下面的代码解决它,但没有成功。
asset_count = 2500
pages = int(math.ceil(asset_count / 1000))
# Get Assets from AtomicHub API
all_assets = []
for page in range(1, pages):
url = f'https://wax.api.atomicassets.io/atomicassets/v1/assets?owner=wax_wallet' \
f'&collection_whitelist=nftdraft2121&page=page&limit=1000&order=asc&sort=name'
response = rq.get(url)
all_assets.append(json.loads(response.text))["response"]
提前感谢您的帮助!
【问题讨论】:
最好使用params
参数而不是手动形成查询字符串:requests.get("https://wax.api.atomicassets.io/atomicassets/v1/assets", params="owner": wax_wallet, "collection_whitelist": "nftdraft2121", "page": "1", "limit": "1000", "order": "asc", "sort": "name")
。你也可以使用response.json()
。
【参考方案1】:
您可以将它们转换为数据帧,然后将各个帧连接成最终结果:
def get_page(page_num):
wax_wallet = "zqsfm.wam"
response = requests.get(
"https://wax.api.atomicassets.io/atomicassets/v1/assets",
params=
"owner": wax_wallet,
"collection_whitelist": "nftdraft2121",
"page": page_num,
"limit": "1000",
"order": "asc",
"sort": "name"
)
json_assets = response.json()
return pd.json_normalize(json_assets['data'])
# The number of pages you want
number_of_pages_requested = 10
# Get all pages as dataframes
pages = [get_page(n + 1) for n in range(number_of_pages_requested)]
# Combine pages to single dataframe
df = pd.concat(pages)
编辑:根据Olvin Roght的评论使用参数更新
编辑 2: 修复索引错误
【讨论】:
不确定您的问题是什么意思。但是使用参数的好建议 您已经编辑了您的答案,包括我来自 cmets 的建议,所以我的问题现在没有意义了。我只是想指出,如果您手动形成 url,则需要将每个值编码为 url 编码,最好使用params
,它会在内部执行此操作。
@tituszban 感谢您的回复!这几乎可以完美地工作;但是,它并没有完全返回我所希望的。我需要返回 3 页,但此代码返回第一页两次,然后返回第二页一次。例如,我有 2,500 个项目跨越 3 个页面。此输出返回 1-1000、1-1000,然后是 1,001-2,000。有什么想法吗?
@python_noob_5,使用range(1, number_of_pages_requested + 1)
@OlvinRoght 是正确的。我更喜欢n + 1
。更新了我的答案【参考方案2】:
我认为这应该会有所帮助:-
import requests
all_assets = []
URL = 'https://wax.api.atomicassets.io/atomicassets/v1/assets'
params =
'owner': 'zqsfm.wam',
'collection_whitelist': 'nftdraft2121',
'page': 1,
'order': 'asc',
'sort': 'name',
'limit': 1000
with requests.Session() as session:
while True:
print(f"Getting page params['page']")
response = session.get(URL, params=params)
response.raise_for_status()
_j = response.json()
data = _j['data']
if len(data) > 0:
all_assets.append(data)
params['page'] += 1
else:
break
print('Done')
【讨论】:
最好避免可能会影响导入的变量名称。无限循环也大多是不好的模式,最好添加一些严格的条件。 我假设您指的是名为“json”的变量。在我不导入json的基础上,我没有看到问题。此外,在这种特殊情况下,无法知道可能会返回多少页。它只能通过请求超出可用范围的页面来推断,当这种情况发生时,就会出现明确定义的条件以上是关于如何从跨多个页面的 GET 请求中提取所有结果?的主要内容,如果未能解决你的问题,请参考以下文章
从跨域 http.get 请求的 ASP.NET Web API 2 响应中获取 Angular 中的特定响应标头(例如 Content-Disposition)