【问题标题】:how to convert response from request.get to DataFrame?如何将响应从 request.get 转换为 DataFrame?
【发布时间】:2025-12-14 19:00:01
【问题描述】:

我有以下代码:

def flatten_json(y):
    out = {}
    def flatten(x, name=''):
        if type(x) is dict:
            for a in x:
                flatten(x[a], name + a + '_')
        elif type(x) is list:
            out[name[:-1]] = x
        else:
            out[name[:-1]] = x
    flatten(y)
    return out 

def importdata(data):
    responsedata = requests.get(urlApi, data=data, headers=hed, verify=False)
    return responsedata


def generatejson(response):
    # Generate flat json file
    sample_object = pd.DataFrame(response.json())['results'].to_dict()
    flat = {k: flat_json(v) for k, v in sample_object.items()}
    return json.dumps(flat, sort_keys=True)

response = importdata(data)
flat_json = generatejson(response)

importdata(data) 返回的示例: https://textuploader.com/dz30p

此代码向 API 发送 get 请求,获取结果解析它们并生成 JSON 文件。

这很好用。

现在,我想修改importdata 函数以支持分页(合并在一起的多个调用)。

所以我写了这段代码:

def impordatatnew():
...
is_valid = True
value_offset = 0
value_limit = 100
datarALL = []
while is_valid:
        is_valid = False
        urlApi = 'http://....?offset={1}&limit={2}&startDate={0}'.format(
            requestedDate,value_offset,value_limit)
        responsedata = requests.get(urlApi, data=data, headers=hed, verify=False)
        if responsedata.status_code == 200:  # Use status code to check request status, 200 for successful call
            responsedata = responsedata.text   
            value_offset = value_offset + value_limit
            # to do: merge the result of the get request
            jsondata = json.loads(responsedata)
            if "results" in jsondata:
                if jsondata["results"]:
                    is_valid = True
            if is_valid:
                # concat array by + operand
                datarALL = datarALL + jsondata["results"]
        else:
            #TODO handle other codes
            print responsedata.status_code
return datarALL

此代码使用分页。它连接到 API,逐页获取结果并将它们组合成一个列表。如果我这样做:

print json.dumps(datarALL) 我看到了组合的 JSON,所以效果很好。 转储示例: https://jsonblob.com/707ead1c-9891-11e8-b651-496f6b276e89

return datarALL 的示例:

https://textuploader.com/dz39d

我的问题:

我似乎无法使impordatatnew() 的返回值与generatejson() 一起使用。如何使impordatatnew() 的返回值与 generatejson() ?我尝试修改如下:

def generatejsonnew(response):
    #Generate flat json file
    sample_object = pd.DataFrame(response.json()).to_dict()
    flat = {k: flat_json(v) for k, v in sample_object.items()}
    return json.dumps(flat, sort_keys=True)

它给出:

sample_object = pd.DataFrame(response.json()).to_dict() AttributeError: 'list' object has no attribute 'json' 我明白这一点,但我不知道如何解决这个问题。我似乎无法进行这种转换。

【问题讨论】:

标签: python json python-requests


【解决方案1】:

它不起作用,因为你这样做:

responsedata = responsedata.text   
jsondata = json.loads(responsedata)
datarALL = datarALL + jsondata["results"]

您在这里所做的似乎是逐步建立一个列表。您可以将其简化为:

dataALL += responsedata.json()

问题来了:

pd.DataFrame(response.json())

这是因为您再次调用 json() 的内容已经从 JSON 解析为 Python 列表。因此出现错误消息。

但真正令人头疼的是你这样做的原因:

sample_object = pd.DataFrame(response.json()).to_dict()

除了将列表重新格式化为字典之外,这并不是真正的“使用 Pandas”。当然有更直接的方法可以做到这一点,例如使用for 循环来构建字典(具体如何,没有样本数据我们无法判断)。

无论如何,如果您想填充 DataFrame,只需删除 .json() 部分,它应该与您的原始非分页代码类似。

但更有效的方法是使用原始代码简单地为每页构建一个 DataFrame,然后调用 pd.concat(pages) 其中pages 是这些 DataFrame 的列表。那么就不需要构建dataALL了。

最终你的代码可以进一步简化,最终变成这样:

pd.concat(pd.read_json(url, ...) for url in all_page_urls)

也就是说,首先你使用一个for循环来构建all_page_urls,然后你使用上面的单线把所有的数据收集到一个单独的DataFrame中。

参考:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_json.html#pandas.read_json

【讨论】:

  • 当我执行sample_object = pd.DataFrame(response).to_dict() 时出现错误flatten(x[a], name + a + '_') TypeError: cannot concatenate 'str' and 'int' objects 我不介意组合功能并更改所需的任何内容,但似乎我所做的一切都会引发另一个问题。
  • 数据样本添加到问题中
  • 在您的代码中,您查找密钥 'results',但您的示例数据不包含此类。
  • datarALL = datarALL + jsondata["results"] 只给出我从 API 调用中得到的部分结果。这是我唯一感兴趣的事情。在原始代码(更改之前)中,importdata 数据只是获取数据而不对其进行操作,所以在 generatejson 中我只考虑 ["results"]
  • 这是 importdata 调用的示例数据(原始函数):textuploader.com/dz30p 它有 total,limit,results,offset 我想得到的实际数据在结果部分。其余的只是我不关心的元数据。