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

Python Aiohttp/Asyncio API请求仅大数据量时触发ContentTypeError排查

问题触发原因
  • API速率限制被触发:你当前的实现会一次性创建所有分页的并发请求,小日期范围下总页数少,并发请求数低于Harvest API的限流阈值,所有请求都能正常返回JSON格式数据;当日期范围扩大后,分页总数激增,短时间内大量并发请求触发了API的速率限制,服务端返回HTML格式的限流提示页面(通常为429状态码),而非预期的JSON结构,因此触发JSON解析错误。
  • 服务端查询超时:过大的日期查询范围会导致部分请求的服务端处理时间超过网关/接口超时阈值,网关会直接返回HTML格式的5xx错误页面,同样无法解析为JSON。
排查方法

修改get_dataset函数,在解析响应前先打印状态码和原始响应内容,即可定位具体错误:

async def get_dataset(session, url):
    async with session.get(url=url, headers=headers, params=params) as resp:
        # 新增调试代码
        if resp.status != 200:
            print(f"请求异常,状态码:{resp.status},响应内容:{await resp.text()}")
        resp_content_type = resp.headers.get("Content-Type", "")
        if "application/json" not in resp_content_type:
            print(f"非预期响应类型:{resp_content_type},响应内容:{await resp.text()}")
            raise Exception(f"响应类型异常:{resp_content_type}")
        dataset = await resp.json()
        return dataset['time_entries']
修复方案

1. 限制并发请求数

使用信号量控制同时发起的请求数量,避免触发API限流,示例如下:

# 全局设置并发数限制,可根据Harvest API限流规则调整,一般设为10-20即可
semaphore = asyncio.Semaphore(10)

async def get_dataset(session, url):
    async with semaphore:
        async with session.get(url=url, headers=headers, params=params) as resp:
            if resp.status != 200:
                # 可增加指数退避重试逻辑
                await asyncio.sleep(2)
                return await get_dataset(session, url)
            dataset = await resp.json()
            return dataset['time_entries']

2. 增加异常容忍机制

将asyncio.gather的return_exceptions参数设为True,避免单个请求失败导致整个任务终止,后续可单独处理失败的请求:

dataset = await asyncio.gather(*tasks, return_exceptions=True)
# 后续过滤处理异常结果
valid_dataset = [entry for entry in dataset if not isinstance(entry, Exception)]

3. 拆分大查询范围

如果日期跨度超过3个月,建议拆分为多个小的时间段分别查询,避免单次查询压力过大触发服务端超时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:27:02