【问题标题】:RestApi json results into a csv using python使用python将Rest Api json结果转换为csv
【发布时间】: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 信息。请看看并帮助我。

标签: python json python-3.x csv rest


【解决方案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 .....
    

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

    1. 来自用户输入 - 交互模式
    2. 来自文件 - 脚本模式

    可以做很多事情,但我会做的是使用 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)
      

      【讨论】:

        猜你喜欢
        • 2020-11-05
        • 1970-01-01
        • 2018-01-04
        • 2019-02-23
        • 2021-09-01
        • 2021-12-03
        • 2019-07-18
        • 1970-01-01
        相关资源
        最近更新 更多