【问题标题】:Python-Aiohttp/Asyncio API request returning ContentTypeError - JSON with unexpected mimetype, but not alwaysPython-Aiohttp/Asyncio API 请求返回 ContentTypeError - JSON 具有意外的 mimetype,但并非总是如此
【发布时间】:2021-09-14 21:41:49
【问题描述】:

我正在尝试发出 API 请求,提取响应的特定块,并最终将其保存到文件中以供以后处理。我还想先提一下,脚本是完整的,直到我开始提取更大的数据集。 当我将参数打开到更大的日期范围时,我收到: 内容类型错误( aiohttp.client_exceptions.ContentTypeError: 0, message='尝试使用意外的 mimetype 解码 JSON:text/html'

async def get_dataset(session, url):
async with session.get(url=url, headers=headers, params=params) as resp:
    dataset = await resp.json()
    return dataset['time_entries']


async def main():
    tasks = []
    async with aiohttp.ClientSession() as session:
        for page in range(1, total_pages):
            url = "https://api.harvestapp.com/v2/time_entries?page=" + str(page)
            tasks.append(asyncio.ensure_future(get_dataset(session, url)))

        dataset = await asyncio.gather(*tasks)

如果我的参数足够小,那么它可以正常工作。但是日期范围太大并且会弹出错误,并且我在上面共享的 sn-p 之后的任何内容都不会运行 更多参考:

url_address = "https://api.harvestapp.com/v2/time_entries/"
headers = {
    "Content-Type": 'application/json',
    "Authorization": authToken,
    "Harvest-Account-ID": accountID
}
params = {
    "from": StartDate,
    "to": EndDate
}

关于什么会导致它在某些数据大小上工作但在更大的集合上失败的任何想法?我假设 JSON 在某些时候格式不正确,但我不确定如何检查和/或防止它发生,因为我能够从 API 中提取多个页面并成功附加到较小的数据提取。

【问题讨论】:

  • 我在我的async with session.post(url, data={json_body} ) 中使用data={json_body},我收到了同样的错误,并且 imo 库抛出的错误有点模糊。然后我将参数更改并重命名为json={json_body},错误得到解决
  • 虽然它不是一个技术上正确的解决方案,但您可以尝试更新您的代码以使用async with session.get(url=url, headers=headers, json=params) as resp: 并查看它是否有效

标签: python json python-requests python-asyncio aiohttp


【解决方案1】:

OP:感谢其他提供答案的人。我发现了这个问题并实施了解决方案。一位朋友指出,如果响应是错误页面而不是预期的 json 内容(即 html 页面提供 429 HTTP 请求过多),aiohttp 可以返回该错误消息。我查看了 API 限制,发现他们确实将其设置为每 15 秒 100 个请求。

我的解决方案是实现asyncio-throttle 模块,它允许我直接限制请求和时间段。你可以在开发者GitHub找到这个

这是我的更新代码和实现,非常简单!对于我的实例,我需要将请求限制为每 15 秒 100 个,您也可以在下面看到。

async def get_dataset(session, url, throttler):
    while True:
        async with throttler:
            async with session.get(url=url, headers=headers, params=params) as resp:
                dataset = await resp.json()
                return dataset['time_entries']


async def main():
    tasks = []
    throttler = Throttler(rate_limit=100, period=15)
    async with aiohttp.ClientSession() as session:
        try:
            for page in range(1, total_pages):
                url = "https://api.harvestapp.com/v2/time_entries?page=" + str(page)
                tasks.append(asyncio.ensure_future(get_dataset(session, url, throttler)))

            dataset = await asyncio.gather(*tasks)

【讨论】:

    猜你喜欢
    • 2021-09-30
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 2013-10-20
    • 2018-02-08
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    相关资源
    最近更新 更多