Я использую 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) Будет ли использование нумерации страниц обойти ограничение на количество записей?
Есть предположения?
«Позволит ли использование нумерации страниц обойти ограничение на количество записей?» - нумерация страниц не обходит ограничение на запрос - например, если ограничение равно 1000 и у вас есть 5000 записей, ваш код в конечном итоге делает 5 запросов, каждый из которых извлекает 1000 записей - например. 1-1000, 1001-2000, 2001-3000, 3001-4000 и 4001-5000. Тем не менее, каждый отдельный запрос по-прежнему соблюдает ограничение в 1000 записей. (Обратите внимание, что иногда вы также можете получить «ограничения скорости», когда вы можете делать только x запросов каждые y минут, но это часто не зависит от размера страницы...)
Сказав это, я не вижу ничего явно неправильного в вашем цикле while
- возможно, попробуйте добавить некоторые журналы, например. ``write-host "uri = '$uri'",
write-host "page = '$($responseData.meta.pagination.current_page)'"``` и т. д., чтобы убедиться, что значения содержат то, что вы ожидаете в каждой точке в петле. Вы также можете попробовать сделать те же запросы вручную в POSTMAN/Fiddler и проверить свои предположения о том, какие значения все на самом деле принимает.
«Разве я не реализовал это правильно?» Вы пробовали его запустить? Что это произвело?
Кстати, я думаю, что нашел документацию по API, основанную на вашем описании разбивки на страницы, и нигде не упоминается .meta.pagination.current_page
или .meta.pagination.total_pages
- возможно, ваш if
эквивалентен if ( $null -eq $null )
и просто выходит из while
на первой итерации, если вы не уверены, что ответ имеет свойство meta
?
Какую версию PowerShell вы используете? В PowerShell 7 вы можете выполнять Invoke-RestMethod ... -FollowRelLink
и получать Invoke-RestMethod
последовательные страницы.
Я поиграл с кодом и сделал то, что мне было нужно:
# 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."
}
ваш API должен дать вам «следующую ссылку» для запроса, вы видите свойство
.next
в$responseData
? было бы проще, если бы вы добавили$responseData | Get-Member -MemberType Properties
к вашему вопросу