You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python中使用for循环处理grequests响应时遭遇JSONDecodeError的技术求助

解决grequests遍历响应时的JSONDecodeError及赋值错误问题

看起来你碰到了两个棘手的小问题:一是部分响应解析JSON时失败,二是循环里的赋值逻辑完全不符合预期。咱们一步步拆解解决:

问题1:JSONDecodeError的根源

grequests.map(rs)返回的响应列表里,大概率存在请求失败的情况——比如某个精灵名称拼写有误,导致API返回404错误;或是网络波动让响应内容为空。这时候调用x.json()自然会报错,因为空内容或者错误页面根本不是有效的JSON格式。
你单独测试s[0].json()能成功,只是刚好第一个请求运气好成功了,但其他请求说不定早就"翻车"了。

问题2:循环赋值的逻辑漏洞

你循环里写的null_data.loc[null_data['name'] == i.capitalize(), 'weight_kg'] = peso里,i是外层for i in null_data['name']循环的最后一个值,不是当前响应对应的精灵名称。最终结果就是所有体重数据都会被赋值给最后一个精灵,完全偏离了你的初衷。

修复后的完整代码

我们需要做这几件事:把请求和对应的精灵名称绑定、先验证响应有效性再解析、捕获异常避免循环中断。

import requests
import json
import grequests

# 准备请求时同时保存对应的精灵名称,避免后续混淆
requests_list = []
pokemon_names = []
for name in null_data['name']:
    url = f'https://pokeapi.co/api/v2/pokemon/{name.lower()}'
    requests_list.append(grequests.get(url))
    pokemon_names.append(name)  # 把每个请求和名称一一对应

# 批量发送请求并获取响应
responses = grequests.map(requests_list)

# 遍历响应和对应的精灵名称,一一处理
for resp, name in zip(responses, pokemon_names):
    # 先判断请求是否有效:响应存在且状态码为200
    if resp and resp.status_code == 200:
        try:
            js_data = resp.json()
            weight_kg = js_data['weight'] / 10
            # 用当前的精灵名称定位DataFrame行,完成赋值
            null_data.loc[null_data['name'] == name, 'weight_kg'] = weight_kg
        except (KeyError, json.JSONDecodeError) as e:
            print(f"处理精灵{name}时出错: {str(e)}")
    else:
        # 打印失败信息,方便排查问题
        status_code = resp.status_code if resp else "无响应"
        print(f"请求精灵{name}失败,状态码: {status_code}")

核心改进点

  1. 请求与名称绑定:用zip(responses, pokemon_names)把每个响应和对应的精灵名称绑定,彻底解决赋值错位的问题
  2. 响应有效性检查:先判断resp是否存在,再检查状态码是否为200,避免解析无效响应
  3. 异常捕获机制:用try-except捕获JSON解析和字段提取时的异常,保证一个请求失败不会导致整个循环终止
  4. 调试友好:打印错误信息,能快速定位是哪个精灵的请求出了问题

这样修改后,既能避开JSON解析报错,也能精准把每个精灵的体重数据对应到DataFrame的正确行里。

内容的提问来源于stack exchange,提问作者Sotovision4K

火山引擎 最新活动