Работа с несколькими JSON из вызовов API в Python - PullRequest
0 голосов
/ 08 апреля 2020

Я пытаюсь сделать несколько вызовов API для получения JSON файлов. Все JSON следуют одной и той же схеме. Я хочу объединить все файлы JSON в один файл, чтобы я мог сделать две вещи:

1) Извлечь все IP-адреса из JSON для работы с более поздними 2) Преобразовать JSON в Pandas Dataframe

Когда я впервые написал код, я сделал один запрос, и он вернул JSON, с которым я мог работать. Теперь я использовал для l oop, чтобы собрать несколько JSON и добавить их в список с именем results_list, чтобы следующий JSON не переписывал предыдущий, который я запросил.

Вот код

headers = {
    'Accept': 'application/json',
    'key': 'MY_API_KEY'
}



query_type = 'QUERY_TYPE'

locations_list = ['London', 'Amsterdam', 'Berlin']

results_list = []

for location in locations_list:

        url = ('https://API_URL' )

        r = requests.get(url, params={'query':str(query_type)+str(location)}, headers = headers)

        results_list.append(r)      



with open('my_search_results.json' ,'w') as outfile:
    json.dump(results_list, outfile)

Файл JSON my_search_results.json содержит отдельную строку для каждого запроса API, например, 0 - Лондон, 1 - Амстердам, 2 - Берлин и c. Например:

    [
    {
        "complete": true,
        "count": 51,
        "data": [
            {
                "actor": "unknown",
                "classification": "malicious",
                "cve": [],
                "first_seen": "2020-03-11",
                "ip": "1.2.3.4",
                "last_seen": "2020-03-28",
                "metadata": {
                    "asn": "xxxxx",
                    "category": "isp",
                    "city": "London",
                    "country": "United Kingdom",
                    "country_code": "GB",
                    "organization": "British Telecommunications PLC",
                    "os": "Linux 2.2-3.x",
                    "rdns": "xxxx",
                    "tor": false
                },
                "raw_data": {
                    "ja3": [],
                    "scan": [
                        {
                            "port": 23,
                            "protocol": "TCP"
                        },
                        {
                            "port": 81,
                            "protocol": "TCP"
                        }
                    ],
                    "web": {}
                },
                "seen": true,
                "spoofable": false,
                "tags": [
                    "some tag",

                ]
            }

(я отредактировал все конфиденциальные данные. В JSON есть отдельная строка для каждого запроса API, представляющая каждый город, но он слишком велик, чтобы показывать здесь)

Теперь я хочу go через JSON и выбрать все IP-адреса:

for d in results_list['data']:
        ips = (d['ip'])
        print(ips)

Однако это выдает ошибку:

TypeError: list indices must be integers or slices, not str

Когда я работал с одним JSON из одного запроса API, это работало нормально, но теперь кажется, что либо JSON не отформатирован должным образом, либо Python видит мой большой JSON как список, а не словарь, хотя я использовал json.dump() на results_list ранее в скрипте. Я уверен, что это связано с тем, как я должен был принять все вызовы API и добавить их в список, но я не могу понять, где я иду не так.

Я пытаюсь выяснить, как выбрать IP-адреса или есть ли лучший способ собрать и объединить несколько JSON. Любой совет приветствуется.

Ответы [ 2 ]

0 голосов
/ 08 апреля 2020

results_list - это список, а не словарь, поэтому results_list['data'] вызывает ошибку. Вместо этого вы должны получить каждый словарь из этого списка, а затем получить доступ к атрибуту 'data'. Отметив также, что значение ключа 'data' относится к списку типов, вам также необходимо получить доступ к элементу этого списка:

for result in results_list:
    for d in result["data"]:
        ips = d["ip"]
        print(ips)

Если вы знаете, что в вашем списке JSON есть только один элемент, Вы можете упростить это до:

for d in results_list[0]["data"]:
    ips = d["ip"]
    print(ips)
0 голосов
/ 08 апреля 2020

Чтобы получить IP, попробуйте:

for d in results_list['data']: #this works only if you accessed data rightly..
        ips = (d[0]['ip'])
        print(ips)

Причина, по которой вы получили ошибку:

Значение данных key представляет собой список, который содержит словарь ip вам нужно. Поэтому, когда вы пытаетесь получить доступ к ip с помощью ips = (d['ip']), вы индексируете внешний список, что вызывает ошибку:

TypeError: индексы списка должны быть целыми или кусочками, а не str


Итак, если:

results_list= [
    {
        "complete": True,
        "count": 51,
        "data": [
            {
                "actor": "unknown",
                "classification": "malicious",
                "cve": [],
                "first_seen": "2020-03-11",
                "ip": "1.2.3.4",
                "last_seen": "2020-03-28",
                "metadata": {
                    "asn": "xxxxx",
                    "category": "isp",
                    "city": "London",
                    "country": "United Kingdom",
                    "country_code": "GB",
                    "organization": "British Telecommunications PLC",
                    "os": "Linux 2.2-3.x",
                    "rdns": "xxxx",
                    "tor": False
                },
                "raw_data": {
                    "ja3": [],
                    "scan": [
                        {
                            "port": 23,
                            "protocol": "TCP"
                        },
                        {
                            "port": 81,
                            "protocol": "TCP"
                        }
                    ],
                    "web": {}
                },
                "seen": True,
                "spoofable": False,
                "tags": [
                    "some tag",

                ]
            }...(here is your rest data)
         ]}]

, чтобы получить все IP-адреса, выполните:

ip_address=[]
# this works only if each result is a seperate dictionary in the results_list
for d in results_list:
    ips = d['data'][0]['ip']
    ip_address.append(ips)
    print(ips)
#if all results are within data
for d in results_list[0]['data']:
    ips = d['ip']
    ip_address.append(ips)
    print(ips)
...