You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python按10分钟间隔拉取API数据报JSONDecodeError排查

问题根因

报错json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)本质是传入json.loads()的内容是空字符串/非JSON格式内容,结合代码逻辑,触发原因有4个:

  • 时间分片逻辑不符合需求且存在越界:代码按10分钟步长生成时间起点,但每个分片的结束时间错误加了20分钟,和需求要求的10分钟分片规则不符,存在大量重复拉取;最后一个时间点(次日00:00)加20分钟后会越界到查询范围外的未来时间,多数API查询无数据的未来时间段会返回空响应。
  • 无HTTP响应状态校验:代码拿到响应后直接读取内容解析,没有校验状态码是否为200,遇到接口限流、权限错误、服务端5xx错误、204无内容响应时,返回的空字符串/HTML错误页/纯文本提示都不是合法JSON,直接解析必报错。
  • 冗余逻辑触发隐藏错误:代码末尾的start_dt += delta、end_dt += delta两行属于冗余逻辑,且delta变量未在代码中定义,第一轮循环跑完就会触发NameError中断任务。
  • 无容错机制:单分片请求失败会直接中断整个批量拉取任务,稳定性差。
修复方案

按以下步骤调整代码即可解决问题:

  1. 修正时间分片规则:严格按照10分钟窗口切分,每个分片的结束时间为起点加10分钟,删除未定义变量的冗余递增逻辑,过滤掉超出结束时间的分片。
  2. 增加响应校验逻辑:先判断HTTP响应状态码,非200状态时记录错误上下文(请求URL、状态码、响应内容),根据场景选择重试或跳过当前分片。
  3. 增加空内容判断:响应内容为空时直接跳过当前分片,不进入JSON解析流程。
  4. 增加单分片异常捕获:单个分片请求/解析失败不中断整体任务,记录错误日志后继续处理下一个分片。

修复后的可运行代码如下:

import json
from datetime import datetime, timedelta
import pandas as pd
import logging

# 日志配置(按需调整)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def call_api(date_run, api_url, headers, client):
    json_arr = []
    batch_start_dt = datetime.strptime(date_run, '%Y-%m-%d')
    batch_end_dt = batch_start_dt + timedelta(days=1)
    # 生成10分钟步长的时间分片起点
    time_points = pd.date_range(start=batch_start_dt, end=batch_end_dt, freq='10T').to_series()
    
    for idx, start_dt_ts in time_points.iteritems():
        start_dt = idx.to_pydatetime()
        # 严格按10分钟窗口设置结束时间,不越界
        end_dt = min(start_dt + timedelta(minutes=10), batch_end_dt)
        # 起点等于终点时直接终止循环
        if start_dt >= batch_end_dt:
            break
        
        start_dt_str = start_dt.strftime('%Y-%m-%dT%H:%M:%S')
        end_dt_str = end_dt.strftime('%Y-%m-%dT%H:%M:%S')
        request_url = f"https://{api_url}:443/api/ChangeList?fromDate={start_dt_str}Z&endDate={end_dt_str}Z&timeBufferInSecs=1200&firstLevelFieldsOnly=true"
        
        try:
            client.request("GET", request_url, headers=headers)
            response = client.getresponse()
            # 先校验状态码
            if response.status != 200:
                err_content = response.read().decode("UTF-8", errors="ignore")
                logging.error(f"分片请求失败,url:{request_url}, 状态码:{response.status}, 响应:{err_content}")
                # 按需加重试逻辑,这里直接跳过当前分片
                continue
            
            data = response.read().decode("UTF-8").strip()
            # 空响应直接跳过
            if not data:
                logging.warning(f"分片{start_dt_str}~{end_dt_str}返回空内容,跳过")
                continue
            
            json_results = json.loads(data)
            # 兼容接口返回字典/列表两种格式
            if isinstance(json_results, list):
                json_arr.extend(json_results)
            else:
                json_arr.append(json_results)
            logging.info(f"分片{start_dt_str}~{end_dt_str}拉取完成,累计获取{len(json_arr)}条数据")
            
        except Exception as e:
            logging.error(f"处理分片{start_dt_str}~{end_dt_str}异常,错误信息:{str(e)}", exc_info=True)
            continue
    
    return json_arr
验证要点
  • 分片区间严格符合10分钟步长要求,无重叠、无越界
  • 单分片异常不影响整体任务运行
  • 非200响应、空响应不会触发JSON解析错误
  • 拉取的数据无重复、无遗漏

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 02:31:05