3

我似乎找不到关于这个主题的任何例子,我想知道如何去做。谁能给我看一个例子或指向一个关于如何使用 Invoke web-request 在 powershell 中进行分页的链接?我面临的挑战是我正在对一次只返回 100 行的服务器进行 API 调用。为了获得更多行,我必须再次调用服务器。我不知道该怎么做。如果有帮助,这里是 Canvas LMS 提供的链接以及我目前拥有的代码。

分页

分页

默认情况下,返回多个项目的请求将分页到 10 个项目。您可以使用 ?per_page 参数设置自定义的每页数量。可以将 per_page 设置为多大有一个未指定的限制,因此请务必始终检查 Link 标头。

要检索其他页面,应使用返回的 Link 标头。这些链接应被视为不透明。它们将是绝对 url,包括检索所需的当前、下一页、上一页、第一页或最后一页所需的所有参数。一个例外是,如果发送 access_token 参数进行身份验证,它将不会包含在返回的链接中,并且必须重新附加。

链接标题中提供了分页信息:

Link:
<https://<canvas>/api/v1/courses/:id/discussion_topics.json?opaqueA>; rel="current",
<https://<canvas>/api/v1/courses/:id/discussion_topics.json?opaqueB>;> rel="next",
<https://<canvas>/api/v1/courses/:id/discussion_topics.json?opaqueC>;> rel="first",
<https://<canvas>/api/v1/courses/:id/discussion_topics.json?opaqueD>;> rel="last" 

可能的 rel 值是:

current - 指向当前结果页面的链接。next - 指向下一页结果的链接。prev - 指向上一页结果的链接。第一 - 链接到结果的第一页。last - 链接到结果的最后一页。只有在相关的情况下才会包含这些内容。例如,结果的第一页将不包含 rel="prev" 链接。如果总计数太昂贵而无法在每个请求上计算,则 rel="last" 也可能被排除在外。

初始产品

$curlly=""
$url_main="https://[instance].instructure.com/api/v1/accounts/1/courses?per_page=1"
$security_token="imhungry"
$header = @{"Authorization"="Bearer "+ $security_token; "rel"="last"}
$curlly=Invoke-WebRequest -Headers $header   -Method Get   -Uri $url_main   
$curlly = ConvertFrom-Json $curlly.Content
foreach($course in $curlly)
{
    $course.name
}
$curlly.Count

最终产品

 ##This is an example on how to use pagination in powershell
$url_main="https://[instance].instructure.com/api/v1/accounts/1/courses?per_page=100"
$security_token="boyimhungry"
$header = @{"Authorization"="Bearer "+ $security_token}
$purlly=Invoke-WebRequest -Headers $header   -Method Get   -Uri $url_main   
$curlly = ConvertFrom-Json $purlly.Content
$url_main = $purlly.Headers.Link.Split(",")[1].Replace("<","").Replace(">","") ## you can get away with just doing one replace("<","") but it looks neater this way
while( !$url_main.Contains("prev"))
{
$purlly=Invoke-WebRequest -Headers $header   -Method Get   -Uri $url_main   
$curlly += ConvertFrom-Json $purlly.Content
$url_main = $purlly.Headers.Link.Split(",")[1].Replace("<","").Replace(">","")
cls
$curlly.Count
$url_main
}
foreach($course in $curlly)
{
    $course.name
}
$curlly.Count
4

3 回答 3

3

我知道你已经接受了一个答案,但我想我会给出我的代码示例,以防万一有人需要。这个例子是获取我们所有 Canvas 用户的列表。不是一个糟糕的过程——大部分工作都是通过一个 4 行的 do..while 循环完成的。

$token = "YOUR_ACCESS_TOKEN"
$headers = @{"Authorization"="Bearer "+$token}
$allCanvasUsers = New-Object System.Collections.ArrayList @()
$pageNumber = 1

Function RequestPageOfUsers($page) {
    $script:resultsPage = Invoke-WebRequest -Method GET -Headers $headers -Uri "https://$domain/api/v1/accounts/self/users?per_page=100&search_term=P00&page=$page"
    $usersPage = ConvertFrom-Json $resultsPage.Content

    foreach ($user in $usersPage) {
        $script:allCanvasUsers.Add($user)
    }
}

do {
    RequestPageOfUsers $pageNumber
    $pageNumber++
} while ($resultsPage.Headers.Link.Contains('rel="next"'))
于 2016-11-14T13:53:05.950 回答
2

大卫贝克的回答太棒了,几乎对我有用,但只返回一页。不知道为什么,但 CONTAINS('...') 测试总是返回 FALSE。

为了让它工作,我不得不对 WHILE 条件做一个小的改变。对我来说,ResultsPage 对象返回一个名为 RelationLink 的属性,该属性是一个包含键值对的字典。分页结果集中的最后一页没有“下一页”键。因此,我的 DO-WHILE 循环一直运行,直到发现“下一个”值为空。

$Token = '<YOUR-TOKEN>'
$headers = @{"Authorization"="Bearer "+$token}
$allCanvasUsers = New-Object System.Collections.ArrayList @()
$pageNumber = 1

Function RequestPageOfUsers($page) {

    $script:resultsPage = Invoke-WebRequest `
        -Method GET `
        -Headers $headers `
        -Uri "https://<DOMAIN>:443/api/v1/accounts/self/users?per_page=100&page=$page"
    $usersPage = ConvertFrom-Json $resultsPage.Content

    foreach ($user in $usersPage) { 
        $script:allCanvasUsers.Add($user)
    }
}

do {
    RequestPageOfUsers $pageNumber
    $pageNumber++
} while ($resultsPage.RelationLink.Next -NE $NULL)
于 2020-03-02T23:56:06.630 回答
1

这看起来像一个真正的痛苦。

在每个分页请求中,您将返回一个Link包含它们描述的一个或多个链接的标头。

出于您的目的(对每个结果的顺序读取),您只需要真正关心链接rel=next链接。你会一直打电话给那个,直到没有rel=next了,这就是你知道你在最后一页的方式。

您不提供 rel 部分;它不是标题。它可以让您确定要使用的链接,然后按原样使用该链接。

因此,您需要做的基本概述:

  1. 提出第一个请求。
  2. 通读返回的Link标题,找到对应的标题rel=next(如果它不存在,你就完成了)。
  3. 直接向您找到的链接发出下一个请求。
  4. 再次解析Link标题,重复。
于 2016-06-09T18:30:31.713 回答