我如何使这个Invoke-Webrequest请求所有的页面?



下面的命令循环遍历一个包含活动ID号的文件,并发送一个请求来检查哪些成员参加了这个活动。这是批处理文件中的PowerShell命令。

Powershell "Get-Content .idsonly.txt | ForEach-Object {Invoke-WebRequest -Method Get -Headers @{ "api-version" = "2" ; "Authorization" = "Bearer %token%"} -Uri %uri%/$_/Members?pagesize=100`&fields=memberid`,hasattended | Select-Object -Expand Content}" ">> memberssact.txt"

问题是一些活动有超过100个成员参加,而这只会给met每个活动的前100个成员。我如何使它要求额外的页面,如果有一个?可以返回的最大结果数是100,这是服务器端的限制。

可能性(但我不知道如何实现它们):

  1. 我有一个活动id列表,旁边是与会者的数量,从中我可以计算出与会者的列表将有多少页。

  2. 有"下一页"url"在响应头中,如果有更多的页面(但我如何告诉PowerShell获取它,如果它在那里?)

  3. 最不喜欢的,但可以只是暴力增加请求的页面数量,并告诉它停止时没有收到响应,但不确定如何。

我在下面提供了一个示例响应头:

{
"access-control-expose-headers": "Request-Context",
"cache-control": "no-cache",
"content-length": "2",
"content-security-policy": "default-src 'self' ;base-uri 'self';  object-src 'none'; connect-src 'self'; worker-src 'none'; upgrade-insecure-requests; frame-ancestors 'self'; child-src 'self'; frame-src 'self'; manifest-src 'self'; prefetch-src 'self'; ; font-src 'self' fonts.gstatic.com data:; img-src 'self' data: *.ac.uk *.swagger.io; media-src 'self' ; script-src 'self' 'unsafe-inline' 'report-sample'; style-src 'self' fonts.googleapis.com 'unsafe-inline' 'report-sample' https://fonts.googleapis.com; report-uri /log",
"content-type": "application/json; charset=utf-8",
"date": "Mon, 23 May 2022 15:37:06 GMT",
"expires": "0",
"last-modified": "Mon, 23 May 2022 15:37:07 GMT",
"pragma": "no-cache",
"request-context": "appId=cid-v1:3abf1c0e-2963-49e7-bc48-18ed8b04daa3",
"strict-transport-security": "max-age=31536000",
"x-content-type-options": "nosniff",
"x-frame-options": "DENY",
"x-pagination": "{"currentPage":3,"pageSize":100,"totalCount":178,"totalPages":2,"previousPageLink":"https://url.uk/activities/597850/students?page=2&pageSize=100&sort=hasattended&fields=studentID%2Chasattended","nextPageLink":""}",
"x-xss-protection": "1; mode=block"
}

既然您已经提供了一个示例响应头,我就更新了下面的代码示例,并提供了它是如何工作的解释:

注意:这个例子没有像一行代码那样调用PowerShell。您应该将这一部分移动到一个脚本中,并为原始命令中使用的每个%VARIABLE%提供一个参数。$Token$Uri是我已更改为PowerShell格式的变量。我还删除了不必要的字符串转义。当然,这可以修改为一行代码,但对于任何真正的脚本逻辑,它应该是自己的脚本、函数等的一部分。

Param(
[string]$Token,
[string]$Uri,
[string]$IdsFile
)
$ids = Get-Content $idsFile
foreach( $id in $ids ) {
$nextUri = "$Uri/$id/Members?pagesize=100&fields=memberid,hasattended"
while( $nextUri ) {
$response = Invoke-WebRequest -Method Get -Headers @{
"api-version" = "2"
Authorization = "Bearer $Token"
} -Uri $nextUri
$response.Content >> membersacct.txt

$paginationHeader = $response.Headers.'x-pagination' | ConvertFrom-Json
$nextUri = $paginationHeader.nextPageLink
}
}

基本上,它的作用是:

  • 添加了输入参数,以方便您使用的CMD变量,并允许您提供idsonly.txt文件的文件路径。这可以与PowerShell脚本一起使用,也可以在PowerShell函数定义中使用。
  • 设置$nextUri为您希望从
  • 获得结果的初始URL
  • 执行web请求,赋值给$response变量
  • 写入(追加)$response.Content文件
  • 使用ConvertFrom-JSONx-pagination头值转换为PowerShell对象。
    • 这导致一个比你可能需要的更大的对象,但它处理JSON的解析,所以你不需要。
  • 设置$nextUri为下一页,即使没有下一页
  • 如果没有$nextPage,则退出while循环
    • 这依赖于$nextUri的真实性;换句话说,空字符串将计算为$False,而任何其他字符串值将计算为$True

最新更新