Python脚本解析API端点JSON数据时遇问题求助
解决Python API数据获取与JSON解析的三类问题
针对你遇到的三个问题,逐个分析成因和解决方案:
1. JSONDecodeError: Expecting value(状态码200仍触发)
成因
- API返回状态码为200,但内容并非合法JSON:比如返回HTML格式的错误提示、空字符串,或编码不匹配导致内容乱码。
- 部分API会在200状态下返回非JSON内容(如维护提示文本)。
解决办法
- 解析前先检查响应的
Content-Type头,确认是application/json再解析。 - 用
try-except单独捕获JSONDecodeError,同时打印响应文本排查问题:
if response.status_code == 200: if 'application/json' in response.headers.get('Content-Type', ''): try: data = response.json() return data except json.JSONDecodeError as e: print(f"JSON解析失败: {e}") print("响应内容:", response.text) return None else: print("响应不是JSON格式") print("响应内容:", response.text) return None
2. requests.exceptions.ConnectionError(偶尔无法建立连接)
成因
- 网络波动、DNS解析失败、API服务器临时不可用。
- API端有限流机制,短时间内请求过多被拒绝。
解决办法
- 设置请求超时时间,避免脚本无限等待:
response = requests.get(url, timeout=10) # 10秒超时
- 添加重试机制,利用
requests适配器实现自动重试:
from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry def fetch_data_from_api(): session = requests.Session() retry = Retry( total=3, # 总重试次数 backoff_factor=1, # 重试间隔时间(1秒、2秒、4秒...) status_forcelist=[429, 500, 502, 503, 504] # 触发重试的状态码 ) adapter = HTTPAdapter(max_retries=retry) session.mount("https://", adapter) session.mount("http://", adapter) try: response = session.get(url, timeout=10) # 后续处理... except Exception as e: print(f"连接错误: {e}") return None
3. AttributeError: 'Response' object has no attribute 'json'
成因
- 使用的
requests版本过旧:response.json()方法在requests 0.12.0版本后才加入,老版本无此方法。 - 代码中意外覆盖了
Response对象,导致其不是标准的requests响应实例。
解决办法
- 升级
requests到最新版本:
pip install --upgrade requests
- 若暂时无法升级,改用
json.loads()手动解析响应文本:
if response.status_code == 200: try: data = json.loads(response.text) return data except json.JSONDecodeError as e: print(f"解析失败: {e}") return None
整合后的完整代码
import requests import json from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry def fetch_data_from_api(): url = "https://api.example.com/data" session = requests.Session() # 设置重试机制 retry = Retry( total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry) session.mount("https://", adapter) session.mount("http://", adapter) try: response = session.get(url, timeout=10) if response.status_code == 200: # 检查响应类型 if 'application/json' in response.headers.get('Content-Type', ''): try: # 优先用response.json(),兼容新版本 data = response.json() return data except (json.JSONDecodeError, AttributeError) as e: # 捕获解析错误或属性错误,改用手动解析 print(f"解析错误: {e}") try: data = json.loads(response.text) return data except json.JSONDecodeError as ee: print(f"手动解析也失败: {ee}") print("响应内容:", response.text) return None else: print("响应非JSON格式") print("响应内容:", response.text) return None else: print(f"请求失败,状态码: {response.status_code}") return None except requests.exceptions.ConnectionError as e: print(f"连接失败: {e}") return None except Exception as e: print(f"未知错误: {e}") return None if __name__ == "__main__": data = fetch_data_from_api() if data: print("数据获取成功") # 后续处理逻辑 else: print("未获取到有效数据")
内容的提问来源于stack exchange,提问作者user22290428
相关产品推荐
相关产品推荐

