Обход лимита записи в вызове API с помощью Powershell

Я использую Powershell для получения списка местоположений с сайта поставщика, используя вызов API:

# Set the initial page and limit values
$page = 1
$limit = 1000

# Initialize an array to hold all the data
$allData = @()

# Set the headers with the token key
$headers = @{
    'Content-Type' = 'application/json'
    'Authorization' = 'Bearer SomeTokenKey'
    'Accept'= 'application/json'
}

# Loop until all data is retrieved
while ($true) {
    # Set the API endpoint URL with the current page and limit values
    $uri = "https://mysite.Someapisite.com/api/locations?page=$page&limit=$limit"

    # Make the API call and retrieve the data
    $responseData = Invoke-RestMethod -Uri $uri -Method GET -Headers $headers -Body $body

    # Add the retrieved data to the allData array
    $allData += $responseData.data

    # Check if all data has been retrieved
    if ($responseData.meta.pagination.current_page -eq $responseData.meta.pagination.total_pages) {
        break
    }

    # Set the page and limit values for the next API call
    $page = $responseData.meta.pagination.current_page + 1
    $limit = $responseData.meta.pagination.per_page
}

# Export all the data to a CSV file
$allData | Export-Csv -Path 'c:\extracts\locations.csv' -NoTypeInformation -Force

У поставщика есть ограничение на извлечение не более 1000 записей за вызов. В документации поставщика API указано, что разбиение на страницы поддерживается:

На сайте используется разбиение на страницы на основе смещения/лимита с помощью параметров limit и page, где смещение рассчитывается автоматически на основе предоставленных параметров.

Link: <https://mySite.someAPIsite.com/api/location?page=3&limit=10>; rel = "next", 
      <https://mySite.someAPIsite.com/api/location?page=7&limit=10>; rel = "last"

Моя цель — извлечь все записи из источника, но приведенный выше скрипт возвращает только 1000 записей.

(A) Разве я не реализовал это правильно?

(B) Будет ли использование нумерации страниц обойти ограничение на количество записей?

Есть предположения?

ваш API должен дать вам «следующую ссылку» для запроса, вы видите свойство .next в $responseData? было бы проще, если бы вы добавили $responseData | Get-Member -MemberType Properties к вашему вопросу

Santiago Squarzon 17.04.2023 20:24

«Позволит ли использование нумерации страниц обойти ограничение на количество записей?» - нумерация страниц не обходит ограничение на запрос - например, если ограничение равно 1000 и у вас есть 5000 записей, ваш код в конечном итоге делает 5 запросов, каждый из которых извлекает 1000 записей - например. 1-1000, 1001-2000, 2001-3000, 3001-4000 и 4001-5000. Тем не менее, каждый отдельный запрос по-прежнему соблюдает ограничение в 1000 записей. (Обратите внимание, что иногда вы также можете получить «ограничения скорости», когда вы можете делать только x запросов каждые y минут, но это часто не зависит от размера страницы...)

mclayton 17.04.2023 21:09

Сказав это, я не вижу ничего явно неправильного в вашем цикле while - возможно, попробуйте добавить некоторые журналы, например. ``write-host "uri = '$uri'", write-host "page = '$($responseData.meta.pagination.current_page)'"``` и т. д., чтобы убедиться, что значения содержат то, что вы ожидаете в каждой точке в петле. Вы также можете попробовать сделать те же запросы вручную в POSTMAN/Fiddler и проверить свои предположения о том, какие значения все на самом деле принимает.

mclayton 17.04.2023 21:09

«Разве я не реализовал это правильно?» Вы пробовали его запустить? Что это произвело?

n0rd 17.04.2023 21:22

Кстати, я думаю, что нашел документацию по API, основанную на вашем описании разбивки на страницы, и нигде не упоминается .meta.pagination.current_page или .meta.pagination.total_pages - возможно, ваш if эквивалентен if ( $null -eq $null ) и просто выходит из while на первой итерации, если вы не уверены, что ответ имеет свойство meta?

mclayton 17.04.2023 22:05

Какую версию PowerShell вы используете? В PowerShell 7 вы можете выполнять Invoke-RestMethod ... -FollowRelLink и получать Invoke-RestMethod последовательные страницы.

Mathias R. Jessen 18.04.2023 03:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я поиграл с кодом и сделал то, что мне было нужно:

# API endpoint
$apiUrl = 'https://someSite.siteUrl.com/api/locations'

# API credentials
$accessToken = 'InsertTokenHere'
      
# Set the limit and initial page
$limit = 1000
$page = 1

# Initialize the locations array
$locations = @()

do {
    # Construct the API request URL with pagination parameters
    $url = '{0}?limit = {1}&page = {2}&expand=locationHours' -f $apiUrl, $limit, $page

    try {
        # Invoke the REST API to fetch locations
        $response = Invoke-RestMethod -Uri $url -Headers @{ Authorization = "Bearer $accessToken" }

        # Add the fetched locations to the locations array
        $locations += $response.data

        # Increment the page number for the next API request
        $page++
    }
    catch {
        # Output the error message and break out of the loop
        Write-Host "API request failed with error: $_"
        break
    }
    
} until ($response.data.Count -ne $limit)

if ($locations) {
    # Output the fetched locations to a CSV file
    $locations | Export-Csv -Path "locations.csv" -NoTypeInformation

    # Output success message with record count
    $recordCount = $locations.Count
    Write-Host "Successfully fetched and saved $recordCount records to locations.csv."
} else {
    Write-Host "No Records were fetched."
}

Другие вопросы по теме