Python: как извлечь данные из Odata API, который содержит страницы @odata.nextLink

#python #api #odata

#python #API #odata

Вопрос:

Мне нужно извлечь данные из Odata API. С помощью приведенного ниже кода я получаю данные, но только 250 строк.

JSON содержит ключ с именем: @odata.nextLink который содержит одно значение, это BASE_URL endpoint ?$skip=250

Как я могу перейти к следующим страницам?

 import requests
import pandas as pd
import json

BASE_URL = "base_url"


def session_token():
    url = BASE_URL   '/api/oauth/token'

    headers = {"Accept": "applicationjson",
                "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"}

    body = {"username":"user",
            "password": "pwd",
            "grant_type": "password"}

    return "Bearer "  requests.post(url, headers = headers, data = body).json()["access_token"]

def make_request(endpoint, token = session_token()):
    headers = {"Authorization": token}
    response = requests.get(BASE_URL   endpoint, headers = headers)
    if response.status_code == 200:
        json_data = json.loads(response.text)
        return json_data


make_request("/odata/endpoint")
  

Следуя совету @Marek Piotrowski, я изменил и пришел к решению:

 def main():
    url = "endpoint"
    while True:
        if not url:
            break
        response = make_request("endpoint")
        if response.status_code == 200:
            json_data = json.loads(response.text)
            url = json_data["@odata.nextLink"] # Fetch next link
            yield json_data['value']

result = pd.concat((json_normalize(row) for row in main()))
print(result) # Final dataframe, works like a charm :)
  

Ответ №1:

Я полагаю, что что-то подобное восстановит все записи (при условии, что они действительно есть @odata.nextLink в json_data ):

 def retrieve_all_records(endpoint, token = session_token()):
    all_records = []
    headers = {"Authorization": token}
    url = BASE_URL   endpoint
    while True:
        if not url:
            break
        response = requests.get(url, headers = headers)
        if response.status_code == 200:
            json_data = json.loads(response.text)
            all_records = all_records   json_data['records']
            url = json_data['@odata.nextLink']
    return all_records
  

Однако код не протестирован. Дайте мне знать, если это сработает. В качестве альтернативы, я полагаю, вы могли бы выполнить какой-нибудь рекурсивный вызов make_request , но тогда вам пришлось бы хранить результаты где-то над самой функцией.

Комментарии:

1. И ?$skip=250 часть?

2. Вы сами написали, что odata.nextLink уже содержит это, верно? Я полагаю, что next odata.nextLink пропустит первые 500 записей и так далее.

3. Спасибо, получил мое решение. Реализуйте свой совет и добавьте немного логики 🙂

4. Приятно это слышать! Был бы признателен, если бы вы приняли ответ тогда. Спасибо!

Ответ №2:

Я знаю, что это поздно, но вы могли бы взглянуть на эту статью из К науке о данных Ephram Мваи

Он довольно решил проблему с помощью хорошего скрипта.