【问题标题】:Importing API json data and converting to a csv for export to Excel in python导入 API json 数据并转换为 csv 以在 python 中导出到 Excel
【发布时间】:2022-01-23 02:53:39
【问题描述】:

我在一家房地产公司工作,我正在尝试创建一个经常更新的 Excel 表格,其中包含公司关于单位/租户/物业/等的所有数据。我们目前使用包含我们所有数据的物业管理网站。该网站有一个 api,我应该可以使用它来访问数据。

我已经尝试从网站的 api 导入数据,并且已经成功导入。话虽如此,导入的数据只是 json 文件的格式,我在将其转换为 csv 时遇到了麻烦。

这是我当前的程序。

'''all imports needed'''
import requests
import pandas as pd
import csv
import json

#get data from api
url ='https://*apiusername:apisecretkey@companyname*.appfolio.com/api/v1/reports/rent_roll.json?columns=Property,PropertyName,PropertyGroupId,PropertyAddress,Unit,Tenant,BdBa,SquareFt,MarketRent,Rent,MoveIn,MoveOut'

try:
    response = requests.get(url).json()
    print("successfully imported json data from appfolio api.")

except IOError:
    print("I/O Error")


#flatten json dictionary just in case
def flattenjson(b, delim):
    print("attempting to flatten json dictionary.")
    val = {}
    for i in b.keys():
        if isinstance(b[i], dict):
            get = flattenjson(b[i], delim)
            for j in get.keys():
                val[i+ delim + j]= get[j]

        else:
            val[i] = b[i]

    return val

test = flattenjson(response, ',')

#print output for test
print(test)

#confirm that test variable is in dictionary format
if isinstance(test, dict):
    print("your imported file is a dictionary.")


#convert dictionary to a csv with pandas
try:
    
    df = pd.DataFrame.from_dict(test)
    print("converted dictionary to pandas dataframe.\n\n")

except:
    print("Error")

try:
    
    df.to_csv("data.csv")
    print("successfully converted dataframe to csv file. attempting to read back data.\n\n")
    df = pd.read_csv("data.csv", index_col=0)
    print(df)

except:
    print("Error")
    

如果我在将导入的 json 字典转换为 csv 之前打印它,这是它当前结构的示例。

{'results': [{'Property': '1020p - 1024 N. roadname Pkwy.城市名,XX 12345'、'PropertyName':'1020p'、'PropertyGroupId':'418024、418031、 418057、418068、418069、418073、418077'、'PropertyAddress':'1020 N。 路名Pkwy。 Cityname, XX 12345', 'Unit': 'Commercial- Loop Lofts Unit B','租户':无,'BdBa':'--/--','SquareFt':'4,888', 'MarketRent':'4,000.00','Rent':无,'MoveIn':无,'MoveOut': 无}, {'Property': '1020p - 1024 N. roadname Pkwy.城市名,XX 12345,'PropertyName':'1020p','PropertyGroupId':'418024、418031、 418057、418068、418069、418073、418077'、'PropertyAddress':'1020 N。 路名Pkwy。 Cityname, XX 12345', 'Unit': '100', 'Tenant': 'John 罗伯茨,'BdBa':'1/1.00','SquareFt':'930','MarketRent': “1,075.00”、“租金”:“1,075.00”、“搬入”:“2021 年 10 月 17 日”、“搬出”: 无}], 'next_page_url': 无}

我相信,由于 API 的工作方式,它正在制作一个嵌套字典,其中第一个键标记为 results,最后一个键标记为 next_page_url

因此,我相信在将字典转换为带有 pandas 的 csv 时,它会将我所有必须处理属性数据的键放在它们自己的列中。这是我想改变的。我当前转换后的 csv 输出如下所示。

    results  next_page_url                      
 0    {'Property': '1020p - 1024 N. roadname Pkwy. St...           NaN
 1    {'Property': '1020p - 1024 N. roadname Pkwy. St...           NaN
 2    {'Property': '1020p - 1024 N. roadname Pkwy. St...           NaN
 3    {'Property': '1020p - 1024 N. roadname Pkwy. St...           NaN
 4    {'Property': '1020p - 1024 N. roadname Pkwy. St...           NaN
 ..                                                 ...            ...
 639  {'Property': 'putinvest - 4240 something Ave....             NaN
 640  {'Property': 'putmgr - 4240 something Ave. St...             NaN
 641  {'Property': 'z4184p - 4184 Something Ave. Jo...             NaN
 642  {'Property': 'z4400p - 4400 Boardwalk Name  St. ...          NaN
 643  {'Property': 'z4514 - 4514 something Ave. St. Lo...          NaN
 
 [644 rows x 2 columns]

理想情况下,来自 api 的每一列,例如 PropertyName、Tenant、PropertyAddress 等,在 csv 中都有自己的列。谁能告诉我如何去格式化它?

谢谢!

【问题讨论】:

  • df = pd.DataFrame(response['results'])

标签: python json pandas api csv


【解决方案1】:

在最终的 CSV 中是否需要 next_page_url

你试过这样做吗?

df = pd.DataFrame(test["results"])

【讨论】:

  • 不,我不需要 nextpageurl。 api文档说明结果是分页的。但我相信文档提供了一个字符串,您可以将其附加到 url 以使其不分页。我会尽快尝试的。我也没有尝试您列出的内容。我不知道我可以用字典中的特定键创建一个数据框,所以谢谢!
【解决方案2】:

我在那个 .json 示例中使用的格式有问题,但您实际上可以使用您导入的 json 库以更简单的方式解决这个问题。

我通常通过保存请求响应来解决这个问题:

response = requests.request("GET", new_url, headers=headers, data=payload)

然后我使用 .loads() 函数将其加载到 python dict 中,然后您可以对其进行索引。

results = json.loads(response.text)['results'][0]

会给你

[{'Property': '1020p - 1024 N. roadname Pkwy.城市名,XX 12345', 'PropertyName':'1020p','PropertyGroupId':'418024、418031、418057、 418068, 418069, 418073, 418077', 'PropertyAddress': '1020 N. roadname PKWY。 Cityname, XX 12345', 'Unit': 'Commercial- Loop Lofts Unit B', '租户':无,'BdBa':'--/--','SquareFt':'4,888','MarketRent': '4,000.00', '租金': 无, '搬入': 无, '搬出': 无}, {'Property': '1020p - 1024 N. roadname Pkwy.城市名,XX 12345, 'PropertyName':'1020p','PropertyGroupId':'418024、418031、418057、 418068, 418069, 418073, 418077', 'PropertyAddress': '1020 N. roadname PKWY。 Cityname, XX 12345', 'Unit': '100', 'Tenant': 'John Roberts', 'BdBa':'1/1.00','SquareFt':'930','MarketRent':'1,075.00','Rent': “1,075.00”、“搬入”:“2021 年 10 月 17 日”、“搬出”:无}]

然后,由于列具有相同的名称,就像使用 pandas 创建 df,然后将其转换为 csv 一样简单。

pd.DataFrame(results).to_csv('~/filename.csv')

【讨论】:

  • 我会尝试使用你的方法,看看会发生什么。你能告诉我设置 data = payload 是什么意思吗?此外,对于 headers=headers,我是否需要将其更改为我需要的确切列,或者只是复制它?
  • 我很抱歉,我只是从我正在处理的另一个项目中复制过来的。您不需要标题或数据参数。 requests.requests() 只需要方法和 url 参数。 data = payload 用于当您想向 URL 发送内容时,标头是您放置身份验证令牌和内容的位置。我主要将它与 REST API 一起使用
  • 非常感谢。我相信这对我有用。我有一个稍微不相关的问题,但是您知道在 python 中是否可以对 csv 数据进行任何分组?我的例子是我有大约 30 个单位出现在相同的属性名称下。是否可以为每个属性名称仅使用一个键,然后在该属性名称的键下列出单元的每条记录和其他详细信息?
  • 在聚合中?是的,pandas 有一个可以使用的 .groupby() 方法。让您的数据在 DataFrame 中以您想要的方式显示,然后使用 .to_csv() 保存它。您不必像我在该示例中所做的那样立即将其保存为 .csv。您可以执行 df = pd.DataFrame(results),然后执行 df.groupby(),然后执行 df.to_csv()。
猜你喜欢
  • 2013-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多