无法从 URL 获取多个 Json 响应

Unable to get multiple Json responses from URL

提问人:Arun.K 提问时间:5/3/2023 最后编辑:Michael RuthArun.K 更新时间:5/5/2023 访问量:75

问:

我将一个 id 值传递给 API url 以获取 JSON 响应,但只得到一个响应,其余的都抛出了 500 个错误。我收集列表中的 id,并在 while 循环中将 id 作为参数传递给 API URL,以提取数据。

###Get id in a variable##     
                                                                                                                                                               
df_filter=spark.sql("""select distinct ID from filter_view""")

rdd = df_filter.rdd
listOfRows = rdd.collect()
counter = 0
##total_results = []
while counter < len(listOfRows):
    url += '?ids=' + listOfRows[counter].ID 
    response = requests.get(url,headers=headers)
       
    if response.status_code == 200:
        json_response = response.json()
        ##total_results.append(json_response)
        df2 = pd.json_normalize(json_response, record_path=['entities'])
        display(df2)
        
    else:
        print("Error: HTTP status code " + str(response.status_code))
    counter +=1

我只得到一个 ID 的输出,其余的都以 500 个错误结束。

期望输出:

ID---ItemID--Details
1    100      text
1    101      text
2    200      text
2    300      text
3    400      sometext
3    500      sometext
   

我得到的输出:

ID---ItemID--Details
1    100     text    
1    101     text
Error: HTTP status code 500
Error: HTTP status code 500
Error: HTTP status code 500
Error: HTTP status code 500
Error: HTTP status code 500
Error: HTTP status code 500
python json 列表 api while-loop

评论

0赞 Michael Ruth 5/3/2023
失败的响应在响应正文中是否有任何内容提供有关错误的详细信息?否则,除非您有权访问远程主机的日志,否则您将不走运,HTTP 状态 500 是内部服务器错误。
0赞 Michael Ruth 5/3/2023
哦,等等,你正在连接每个迭代。别这样。尝试。'?ids=...'response = requests.get(url + '?ids=' + listOfRows[counter].ID, headers=headers)
0赞 Michael Ruth 5/3/2023
为了一个最小的可重复的例子,在问题中定义也很好url
0赞 Arun.K 5/3/2023
@MichaelRuth - 我无法提供实际的 URL,因为它是供应商许可的

答:

1赞 Michael Ruth 5/3/2023 #1

第一次迭代会生成一个有效的 URL:,但由于它是使用串联和赋值构建的,因此第二次迭代会在需要时生成 。baseURL/?ids=1baseURL/?ids=1?ids=2baseURL/?ids=2

while counter < len(listOfRows):
    response = requests.get(f'{url}?ids={listOfRows[counter].ID}', headers=headers)

API 是否支持在单个请求中获取多个资源?通常,对于复数查询参数(如 ),它将采用逗号分隔的资源 ID 列表 () 或数组 (, 或 )。如果是这样,那么提出这样的请求会更有效率,对 API 提供者来说也更礼貌。ids?ids=1,2,3?ids[]=1&ids[]=2&ids[]=3?ids=1&ids=2&ids=3

response = requests.get(
    url + '?ids=' + ','.join([row.ID for row in listOfRows]),
    headers=headers
)

您可能需要更改代码来分析新响应。

如果不支持多个 GET,请至少将其转换为 for 循环。无需跟踪和测试,它将提高可读性。countercounter < len(listOfRows)

df_filter=spark.sql("""select distinct ID from filter_view""")

rdd = df_filter.rdd
listOfRows = rdd.collect()
for row in listOfRows:
    response = requests.get(f'{url}?ids={row.ID}', headers=headers)
       
    if response.status_code == 200:
        json_response = response.json()
        df2 = pd.json_normalize(json_response, record_path=['entities'])
        display(df2)
        
    else:
        print("Error: HTTP status code " + str(response.status_code))

更新:基于评论

我有 5000 多个 ID 需要一一传递。这怎么能在 20 个块中通过?

生成表单的 URL,每个 URL 不超过 20 个 ID。...?ids=1&ids=2&ids=3...

from itertools import islice
def chunker(it: seq, chunksize):
    iterator = iter(it)
    while chunk := list(islice(iterator, chunksize)):
        yield chunk

for id_chunk in chunker([row.ID for row in listOfRows], 20):
    response = requests.get(
        f'{url}?ids=' + '&ids='.join(id_chunk),
        headers=headers
    )

将可迭代对象拆分为长度为 <= 的 s。首先筛选仅 ID。然后将 ID 分块为长度为 20 的 s。生成 URL 并发出请求。 感谢kafran的chunker()。chunker()listchunksizelistOfRowslist

评论

0赞 Arun.K 5/3/2023
谢谢你@Michael露丝,我会尝试在这里更新。
0赞 Arun.K 5/3/2023
URL 不接受多个 ID,其抛出错误代码 414。所以我按照你的建议求助于for循环,它可以带来一段时间的数据,但后来抛出错误:HTTP状态代码401。我也尝试了while循环,在运行几分钟后出现同样的问题,它抛出错误错误:HTTP状态代码401
0赞 Michael Ruth 5/3/2023
@Arun.K,401 状态表示未授权,请求者未为资源提供有效的身份验证凭据。如果每次都相同,我敢打赌它会在同一资源上失败。打印 ID 和状态代码进行验证。listOfRows
0赞 Arun.K 5/4/2023
我与供应商核实了一下,他们说 API 支持多个 GET 请求,但它应该采用这种格式 ==> 条目?Ids=<第一个>&Ids=<第二个>&Ids=<第三个>....等等。此外,我有超过 5000 个 ID 需要一一传递。这怎么能在 20 个块中通过?
0赞 Arun.K 5/4/2023
根据您上面的建议,我认为这会起作用?ids=1&ids=2&ids=3)如何在for循环中将其传递到URL中?