科技 · 实用指南
requests 报 JSONDecodeError char 0?解析前先证明响应字节
保存最终 URL、状态码、Content-Type、原始字节长度和安全前缀,再区分合法空响应、HTML/文本、已消费流与真正 JSON。

“Expecting value: line 1 column 1 (char 0)” 只说明解析器在起点没有找到 JSON 值,并不证明引号、库或服务器一定有问题。
重试前固定同一次响应的请求、跳转、状态、媒体类型、字节长度和脱敏前缀,让证据指向真正的 HTTP 或流边界。
重试前冻结一次失败交换
记录同一次失败调用的方法、脱敏目标、status_code、最终 URL 和跳转历史;有条件时保存时间与关联 ID。
不要记录凭据、Cookie、Authorization 或无限正文;只保存选择后的头与短脱敏前缀。
选解析器前先测量字节
把 response.content 一次读入受限变量并记录长度;零字节说明根本没有 JSON 文档。
若使用 stream=True,要证明谁拥有读取权;iter_content、raw.read 或中间件可能已把流推进到末尾。
联合解释状态、跳转与 Content-Type
Requests 明确说明 204 或无效正文会让 json() 抛错;204 可能是合法结果,应按接口契约返回“无对象”。
检查最终 URL 和跳转;登录页、限流页、404 HTML 与 502 网关页常以“<”开头并在 char 0 失败。
区分 HTTP 失败和表示失败
是否先 raise_for_status 取决于 API 契约;有些错误状态返回 JSON,有些返回 HTML。
状态异常先修认证、端点、跳转、代理或上游;状态正常但正文类型不符,则保留样本并报告表示契约违约。
只解析一次并证明退出条件
确认契约允许 JSON 且字节非空后,才调用 response.json() 或 json.loads(body)。
用同一运行时和网络路径重放:状态符合预期、类型兼容、字节非零、解析成功且 schema 通过,才算结案。
