Invoke-WebRequest Canvas LMS API分页

时间:2016-06-09 17:15:48

标签: powershell pagination canvas-lms

我似乎无法找到关于此主题的任何示例,我想知道如何做到这一点。 任何人都可以向我展示一个示例或指向我如何使用Invoke web-request在powershell中进行分页的链接吗?我面临的挑战是我正在对只返回的服务器进行API调用一次100行。为了获得更多行,我将不得不再次调用服务器。我不知道怎么做。 如果它有帮助,这里是Canvas LMS提供的链接和我到目前为止的代码。

Pagination

  

分页

     

返回多个项目的请求将被分页到10个项目   默认。您可以使用?per_page设置每页自定义数量   参数。您可以设置的大小有一个未指定的限制   per_page to,所以一定要检查链接头。

     

要检索其他页面,应返回返回的链接标头   用过的。应将这些链接视为不透明。他们将是绝对的   包含检索所需参数所需的所有参数的网址   当前,下一个,上一个,第一个或最后一页。唯一的例外是   如果发送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值为:

     

当前 - 链接到当前结果页面。下一个 - 链接到下一个   结果页面。 prev - 链接到上一页的结果。第一 -   链接到结果的第一页。最后 - 链接到最后一页   结果。只有在相关时才会包含这些内容。对于   例如,结果的第一页不包含rel =&#34; prev&#34;链接。   的rel =&#34;最后&#34;如果总数太贵,也可能被排除在外   计算每个请求。

初期产品

$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

3 个答案:

答案 0 :(得分:1)

这看起来真的很痛苦。

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

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

你没有提供相关部分;它不是标题。它可以帮助您识别要使用的链接,然后按原样使用该链接。

所以你需要做的基本概述:

  1. 提出第一个请求。
  2. 仔细阅读返回的Link标题,找到与rel=next对应的标题(如果不存在,则表示您已完成)。
  3. 直接向您找到的链接发出下一个请求。
  4. 再次解析Link标题,重复。

答案 1 :(得分:1)

我知道你已经接受了答案,但我想我会给出我的代码示例以防万一有人需要。这个例子是获取我们所有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"'))

答案 2 :(得分:1)

大卫·贝克(David Baker)的回答很棒,几乎为我工作,但只返回了一页。不知道为什么,但是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)