使用python将Rest Api json结果转换为csv

Posted

技术标签:

【中文标题】使用python将Rest Api json结果转换为csv【英文标题】:RestApi json results into a csv using python 【发布时间】:2021-10-11 21:06:01 【问题描述】:

我正在尝试将从RestApi URL 返回的响应写入csv 文件,用于提供port number(交互模式)和选定用户users_list.txt(脚本模式)。我有下面的代码来完成这项工作。

import json
import csv
import urllib.request
import subprocess

portvalue = input("Please enter an Port Number:\n")
portvalue = int(portvalue)
print(f'You entered portvalue')

tooluser='admin'
toolpassword='password'

user = open('users-list.txt')
for line in user:
   bash_com = 'curl --user tooluser:toolpassword http://198.98.99.12:46567/portvalue/protects/user  \
         | jq --arg a_port portvalue --arg a_userid user 'map(.+"userid":user+"port":portvalue)'' as url:

subprocess.Popen(bash_com)
output = subprocess.check_output(['bash','-c', bash_com])
print(line)
myfile.close()

# with urllib.request.urlopen("curl --user admin:password http://198.98.99.12:46567/port/protects/user | jq") as url:

data = json.loads(url.read().decode())

fname = "output.csv"

with open(fname, "w") as file:
    csv_file = csv.writer(file,lineterminator='\n')
 csv_file.writerow(["depotFile","host","isgroup","line","perm","user","port","userid"])
    for item in data["raw_data"]:
        csv_file.writerow([item['depotFile'],item['host'],item['isgroup'],item['line'],item['perm'],item['user'],item['port'],item['userid']])

使用 URL 获取单个用户的数据 - curl --user admin:password http://198.98.99.12:46567/2324/protects/sanchez.ricardo | jq

users_list.txt 由以下格式的用户组成。

sanchez.ricardo
varun.sharma
daniel.vel

json输出格式之一如下,

[
  
    "depotFile": "//LIB/Include/...",
    "host": "*",
    "isgroup": "",
    "line": "19",
    "perm": "open",
    "user": "5G",
    "port": "2324",
    "userid": "sanchez.ricardo"
   ,
....
......
.........
]

预期的输出 csv 文件:-

Sno     depotFile       host  isgroup  line   perm    user    port  userid
1   //LIB/Include/...   *              19     open    5G      2324  sanchez.ricardo
2   //LIB/...           *              19     write   6G      2324  varun.sharma
3   //AND/RIO/...       *              20     write   AND     2324  daniel.vel

我无法处理上述代码中的RestApi URl。请帮助我在 python 中实现这一点。提前感谢您的帮助。

【问题讨论】:

如果您仍然需要这方面的帮助,您能否添加一个包含两个用户的用户列表示例文件,以及您为获取两个用户的 csv 所点击的实际 url? @ Brian Z,是的,我仍在寻求帮助。我在问题中添加了userlist 文件和实际url 信息。请看看并帮助我。 【参考方案1】:

我喜欢使用请求来抓取东西,因为它现在很容易,比一开始有了很大的改进。它比 pyCurl 容易得多,因为我正在重构代码以使用它,因为我会随着时间的推移对代码进行改进。

这是一个非常酷的网站,可以将 curl 命令转换为请求代码:

https://curl.trillworks.com/

所以:

curl --user admin:password http://198.98.99.12:46567/2324/protects/sanchez.ricardo

是:

import requests

response = requests.get('http://198.98.99.12:46567/2324/protects/sanchez.ricardo', auth=('admin', 'password'))

现在在我看来,您的循环无法正常工作。它循环并将这些东西分配给bash,但在循环完成之前不做任何事情。可能你不小心取消了它。无论如何,这是一个应该工作的循环,使用另一个答案中建议的 f-strings 的建议。

我不完全确定你从 api 得到什么,似乎你需要为每个请求发出多个请求来获取 json,所以我是这样写的。我相信你需要调整一些东西,但这应该会让你更接近。

import requests
import json
import csv
user_csv = '''sanchez.ricardo
varun.sharma
daniel.vel'''
# I cannot tell where you get the ports from, so I will put a list here to show the code working
# and you can fill it differently, maybe from the csv?? not sure
ports = [2324, 2324, 2324]
users = user_csv.split('\n')
fname = "output.csv"
with open(fname, "w") as file:
    csv_file = csv.writer(file,lineterminator='\n')
    csv_file.writerow(["depotFile", "host", "isgroup", "line", "perm", "user", "port", "userid"])
    for user, port in zip(users, ports):
        print(f'from csv and other method here is the user and port: user, port')
        url = f'http://198.98.99.12:46567/port/protects/user'
        print(f'grab data from rest api: url')
        # cannot tell if there is one user:password for the REST API, this code assumes so
        response = requests.get(url, auth=('admin', 'password'))
        # assuming response returns json like this:
        # response = '''[
        #   
        #     "depotFile": "//LIB/Include/...",
        #     "host": "*",
        #     "isgroup": "",
        #     "line": "19",
        #     "perm": "open",
        #     "user": "5G",
        #     "port": "2324",
        #     "userid": "sanchez.ricardo"
        #    ]'''
        data = json.loads(response)
        for item in list(data):
            csv_file.writerow(item.values())

【讨论】:

【参考方案2】:

在这种情况下,f-string 可能就是您要查找的内容。考虑一下:-

user='sanchez.ricardo'
port=2324

url = f'http://198.98.99.12:46567/port/protects/user'

【讨论】:

'port' 是运行时输入变量,'user' 我需要从文本文件中传递。这种情况python怎么处理? 使用 input() 直接从用户获取信息(交互式)或传递命令行参数以获取端口值。打开文件并读取其内容以获取用户详细信息 您是否注意到当您尝试运行该代码时发生了什么?毫无疑问,urlopen 需要一个 URL 我只需要传递URL 而不是Curl along with URL 很遗憾,由于我无法访问主机站点,因此我无法为您编写和测试任何代码【参考方案3】:

你的第二个 sn-p 只覆盖了部分

curl --user $USERID:$PASSWORD http://198.98.99.12:46567/$PORT/protects/$u \
          jq --arg a_port $PORT --arg a_userid .....

据我了解,您需要两种功能

    来自用户输入 - 交互模式。 来自文件 - 脚本模式

可以做很多事情,但我会做的是使用 Argeparse 并且可能有一个开关参数 -ulf|--users-list-file 来传递文件,或者根本没有交互模式的参数。

并通过环境变量传递端口,并使用os.environ 以及-p|--port 作为可选参数来读取它

一种快速而肮脏的方法是使用sys.argv 读取传递的参数并相应地编写您的条件。

【讨论】:

【参考方案4】:

我一直在浏览您的代码,您可以简单地使用request 并使用pandas 将数据存储在CSV 中。这将使输出变得容易。

import json
import pandas as pd
json_string = ' "name":"John", "age":30, "car":"None" '

a_json = json.loads(json_string)
print(a_json)

dataframe = pd.DataFrame.from_dict(a_json)

【讨论】:

以上是关于使用python将Rest Api json结果转换为csv的主要内容,如果未能解决你的问题,请参考以下文章

将 JSON 请求循环到后端(REST API)

ActiveCollab REST API 使用 Python 接收的嵌套 JSON 中的访问值 [已解决]

显示rest api json响应,如使用angular js的文本框自动填充

Python json unicode转中文

Android REST API 连接

如何从 Python REST API 返回 JSON