PowerShell 命令行 HTTP 请求:Invoke-WebRequest 详解 – wiki基地


深入解析 PowerShell 命令行 HTTP 请求:Invoke-WebRequest 详解

在日常的系统管理、自动化脚本编写以及与现代Web服务进行交互中,执行HTTP请求是一个非常常见的任务。无论是下载文件、与RESTful API通信、抓取网页信息,还是模拟用户登录,PowerShell 都提供了一个强大而灵活的工具来完成这些工作:Invoke-WebRequest cmdlet。

本文将带您深入探索 Invoke-WebRequest 的方方面面,从最基本的用法到复杂的场景,帮助您完全掌握如何在命令行中优雅地发起和处理HTTP请求。我们将详细讲解其各种参数、输出对象的结构、如何发送不同类型的数据、处理响应、管理会话、以及它与另一个常用cmdlet Invoke-RestMethod 的区别。

1. 认识 Invoke-WebRequest

Invoke-WebRequest,简称 iwr,是 PowerShell 中用于向Web服务器发送 HTTP、HTTPS、FTP 请求,并接收响应的核心 cmdlet。它的设计目标是提供一个命令行界面的浏览器功能,能够模拟用户访问网页或应用程序的行为。

与传统的 curlwget 工具类似,Invoke-WebRequest 允许你指定请求的URI(统一资源标识符)、HTTP方法(GET、POST、PUT、DELETE等)、请求头、请求体等信息。然而,作为PowerShell的内置cmdlet,它返回的不仅仅是原始的文本响应,而是一个结构化的对象,这个对象包含了状态码、响应头、内容,甚至是经过解析的HTML文档结构(在Windows PowerShell中尤其强大),这使得后续的处理变得异常便捷。

Invoke-WebRequest 的主要用途包括:

  • 下载文件: 快速从Web或FTP服务器下载文件。
  • 访问网页: 获取网页的HTML内容。
  • 与Web API交互: 发送请求到RESTful或其他Web服务接口,获取或发送数据。
  • 网页抓取 (Web Scraping): 解析HTML内容,提取所需信息(虽然对于复杂网页抓取可能有局限性,但对简单结构有效)。
  • 自动化任务: 在脚本中集成与Web服务的交互,例如检查网站状态、触发远程操作等。

总而言之,Invoke-WebRequest 是 PowerShell 中进行 Web 交互的瑞士军刀。

2. 基本用法:发起 GET 请求

HTTP 最常见的请求方法是 GET。当你在浏览器地址栏输入一个网址并回车时,通常就是发起一个 GET 请求。使用 Invoke-WebRequest 发起 GET 请求非常简单,只需要指定 -Uri 参数即可。

powershell
Invoke-WebRequest -Uri "https://www.example.com"

执行上述命令后,Invoke-WebRequest 会向 https://www.example.com 发起一个 GET 请求,并将服务器的响应作为对象返回。在默认情况下,PowerShell 会格式化并输出这个对象的关键属性。

典型的输出可能包含:

StatusCode : 200
StatusDescription : OK
Content : <!doctype html>
<html>
<head>
<title>Example Domain</title>
... (页面HTML内容) ...
Relationships : {}
RawContent : HTTP/1.1 200 OK
Content-Encoding: gzip
Accept-Ranges: bytes
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
... (原始HTTP响应头和内容) ...
Forms : {}
Headers : {[Content-Encoding, gzip], [Accept-Ranges, bytes], [Cache-Control, max-age=604800], [Content-Type, text/html; charset=UTF-8]...}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : mshtml.HTMLDocumentClass
RawContentLength : 648

这个输出对象非常重要,它包含了服务器响应的所有关键信息:

  • StatusCode: HTTP 状态码 (例如 200 表示成功,404 表示未找到)。
  • StatusDescription: 状态码对应的文本描述。
  • Content: 服务器返回的响应体内容,通常是字符串形式(HTML、JSON、XML等)。
  • RawContent: 完整的原始 HTTP 响应,包括状态行、响应头和响应体。
  • Headers: 响应头信息的集合,可以用来查看 Content-Type、Set-Cookie 等信息。
  • ParsedHtml: (在 Windows PowerShell 中可用) 如果响应内容是 HTML,这是一个解析后的 HTML 文档对象,允许你像操作DOM一样通过编程方式访问页面元素。这在 PowerShell Core 中可能不可用或行为不同。
  • Links, Images, Forms, InputFields, Relationships: (主要依赖于 -ParsedHtml) Invoke-WebRequest 会尝试从 HTML 中解析出这些元素的集合,方便进行进一步处理。

你可以将这个返回对象存储到一个变量中,以便进一步处理:

“`powershell
$response = Invoke-WebRequest -Uri “https://www.example.com”

查看状态码

$response.StatusCode

查看响应头

$response.Headers

查看响应内容

$response.Content

(如果响应是HTML) 查看解析后的HTML文档的标题

注意:ParsedHtml的可用性和行为可能因PowerShell版本和操作系统而异

if ($response.ParsedHtml) {
$response.ParsedHtml.title
}
“`

3. 指定 HTTP 方法

除了 GET,Invoke-WebRequest 支持所有标准的 HTTP 方法,通过 -Method 参数指定。常用的方法包括 POST、PUT、DELETE。

3.1 POST 请求

POST 请求通常用于向服务器提交数据,例如提交表单或发送API请求体。使用 -Method POST 参数来指定 POST 请求,并使用 -Body 参数来发送数据。

-Body 参数可以接受多种类型的数据:

  • 字符串: 直接发送文本数据。
  • 哈希表 (Hashtable): 常用于发送 URL 编码的表单数据。Invoke-WebRequest 会自动将哈希表转换为 key1=value1&key2=value2 的格式,并设置 Content-Typeapplication/x-www-form-urlencoded (除非你手动指定了 Content-Type)。
  • 文件路径: 发送文件的内容作为请求体。

示例 1:发送 URL 编码的表单数据 (使用哈希表)

“`powershell
$formData = @{
username = “testuser”
password = “testpassword”
rememberme = “true”
}

注意:替换为实际的登录或数据提交URL

$loginResponse = Invoke-WebRequest -Uri “https://example.com/login” -Method POST -Body $formData
“`

在这个例子中,$formData 哈希表会被自动转换为 username=testuser&password=testpassword&rememberme=true 并作为请求体发送。

示例 2:发送 JSON 数据 (需要手动指定 Content-Type)

与许多现代 API 交互时,通常需要发送 JSON 格式的数据。你需要将 PowerShell 对象转换为 JSON 字符串,然后将其作为 -Body 发送,并设置 Content-Typeapplication/json

“`powershell
$jsonData = @{
name = “PowerShell User”
role = “Automation Engineer”
}

$jsonBody = $jsonData | ConvertTo-Json

注意:替换为实际的API端点URL

$apiResponse = Invoke-WebRequest -Uri “https://api.example.com/users” -Method POST -Body $jsonBody -ContentType “application/json”
“`

ConvertTo-Json cmdlet 用于将 PowerShell 对象(如哈希表或自定义对象)转换为 JSON 格式的字符串。-ContentType 参数用于告知服务器请求体的数据格式。

示例 3:发送 XML 数据 (需要手动指定 Content-Type)

类似地,如果你需要发送 XML 数据:

“`powershell

这是一个简单的XML字符串示例,实际中可能更复杂

$xmlBody = @”

Xml User
Data Analyst

“@

注意:替换为实际的API端点URL

$apiResponse = Invoke-WebRequest -Uri “https://api.example.com/data” -Method POST -Body $xmlBody -ContentType “application/xml”
“`

3.2 PUT 和 DELETE 请求

PUT 请求通常用于更新资源,而 DELETE 请求用于删除资源。它们的使用方式与 POST 类似,区别在于 -Method 参数:

示例:发送 PUT 请求

“`powershell
$updateData = @{
role = “Senior Automation Engineer”
}
$updateJson = $updateData | ConvertTo-Json

注意:替换为实际的资源更新URL,通常包含资源ID

$updateResponse = Invoke-WebRequest -Uri “https://api.example.com/users/123” -Method PUT -Body $updateJson -ContentType “application/json”
“`

示例:发送 DELETE 请求

DELETE 请求通常不包含请求体,但有时 API 设计可能会允许。最常见的用法是指定资源 URI。

“`powershell

注意:替换为实际的资源删除URL,通常包含资源ID

$deleteResponse = Invoke-WebRequest -Uri “https://api.example.com/users/123” -Method DELETE
“`

4. 发送查询参数

对于 GET 请求,数据通常通过 URL 的查询字符串发送。你可以在 -Uri 参数中直接包含查询参数,例如 https://api.example.com/search?query=test&page=1

“`powershell
$searchQuery = “PowerShell”
$pageNumber = 2

$searchUri = “https://api.example.com/search?query=$searchQuery&page=$pageNumber”

$searchResponse = Invoke-WebRequest -Uri $searchUri -Method GET
“`

另一种更规范且避免手动编码的方式是使用 -QueryString 参数。-QueryString 接受一个哈希表,Invoke-WebRequest 会负责将其转换为正确的 URL 查询字符串格式并进行 URL 编码。

“`powershell
$queryParams = @{
query = “PowerShell HTTP”
page = 3
format = “json”
}

$searchResponse = Invoke-WebRequest -Uri “https://api.example.com/search” -QueryString $queryParams -Method GET
“`

这种方式对于包含特殊字符的查询参数尤其有用,因为它会自动处理 URL 编码。

5. 处理响应内容

如前所述,Invoke-WebRequest 返回的对象包含了 .Content 属性,它是响应体内容的字符串表示。根据 Content-Type 头,这个内容可能是 HTML、JSON、XML、纯文本或其他格式。

5.1 处理 JSON 响应

当与 RESTful API 交互时,响应内容通常是 JSON 格式(Content-Type: application/json)。虽然 .Content 属性是字符串,但你可以使用 ConvertFrom-Json cmdlet 轻松地将其转换为 PowerShell 对象,这样你就可以像访问对象的属性一样访问 JSON 数据。

“`powershell
$apiResponse = Invoke-WebRequest -Uri “https://api.example.com/users/456” -Method GET -Headers @{“Accept”=”application/json”}

检查状态码是否成功

if ($apiResponse.StatusCode -eq 200) {
# 将JSON字符串转换为PowerShell对象
$userData = $apiResponse.Content | ConvertFrom-Json

# 现在可以像访问对象属性一样访问数据
Write-Host "User Name: $($userData.name)"
Write-Host "User Role: $($userData.role)"

# 如果JSON是数组
# $userList = $apiResponse.Content | ConvertFrom-Json
# $userList[0].name

} else {
Write-Host “Error fetching user data. Status Code: $($apiResponse.StatusCode)”
}
“`

这是与现代 API 交互时最常用的模式之一:Invoke-WebRequest -> 检查状态码 -> ConvertFrom-Json -> 处理 PowerShell 对象。

5.2 处理 HTML 响应 (使用 ParsedHtml)

在 Windows PowerShell 中,如果响应内容是 HTML (Content-Type: text/html),Invoke-WebRequest 会尝试使用内置的 IE 解析引擎来构建一个 ParsedHtml 对象。这个对象是 mshtml.HTMLDocumentClass 的实例,它提供了类似 DOM 的结构,允许你通过各种方法和属性访问 HTML 元素的集合。

注意: ParsedHtml 的可用性和功能在 PowerShell Core (Linux, macOS, Windows) 中可能受限或不可用,或者依赖于具体的运行时环境。在跨平台脚本中,依赖 .Content 和其他解析技术(如正则表达式或第三方库)可能更可靠。但在 Windows PowerShell 中,ParsedHtml 是一个强大特性。

示例:使用 ParsedHtml 提取链接

“`powershell

注意:在PowerShell Core中此示例可能无法正常工作或需要额外配置

$webpage = Invoke-WebRequest -Uri “https://www.example.com”

if ($webpage.ParsedHtml) {
# 获取所有链接 ( 标签)
$links = $webpage.ParsedHtml.getElementsByTagName(“a”)

# 遍历并输出链接文本和 href 属性
foreach ($link in $links) {
    Write-Host "Link Text: $($link.innerText)"
    Write-Host "Link URL: $($link.href)"
    Write-Host "---"
}

# 获取特定ID的元素
# $elementById = $webpage.ParsedHtml.getElementById("someId")

# 获取带有特定CSS类的元素 (如果getElementById等方法可用)
# $elementsByClass = $webpage.ParsedHtml.getElementsByClassName("someClass") # 注意:getElementsByClassName 在较旧的MSHTML版本中可能不存在
# 或者使用querySelectorAll (如果可用)
# $elementsByQuery = $webpage.ParsedHtml.querySelectorAll(".someClass")

} else {
Write-Host “ParsedHtml is not available or could not parse the content.”
# 可以考虑使用正则表达式或其他方法解析 $webpage.Content
}
“`

使用 ParsedHtml 可以方便地进行简单的网页抓取,提取特定元素的内容、属性或链接。但是,对于复杂的、动态加载内容的网页(依赖JavaScript渲染),Invoke-WebRequestParsedHtml 功能可能力不从心,因为它不像真正的浏览器那样执行JavaScript。

6. 发送自定义请求头

HTTP 请求头提供了关于请求或请求体以及客户端的重要信息,例如 User-AgentAcceptAuthorizationCookie 等。你可以使用 -Headers 参数发送自定义请求头。-Headers 接受一个哈希表,其中键是头名称,值是头值。

“`powershell
$headers = @{
“User-Agent” = “MyPowerShellScript/1.0”
“Accept” = “application/json”
“X-Custom-Header” = “SomeValue”
}

$response = Invoke-WebRequest -Uri “https://api.example.com/data” -Method GET -Headers $headers
“`

发送 User-Agent 头可以帮助服务器识别请求的客户端。发送 Accept 头可以告知服务器你希望接收哪种类型的响应内容。自定义头 (如 X-Custom-Header) 常用于 API 身份验证或传递特定的请求元数据。

身份验证头:

许多 API 使用 Authorization 头进行身份验证,例如 Bearer Tokens 或 Basic Authentication。

  • Bearer Token:
    powershell
    $token = "your_api_bearer_token"
    $authHeader = @{
    "Authorization" = "Bearer $token"
    }
    $secureResponse = Invoke-WebRequest -Uri "https://api.example.com/secure_data" -Method GET -Headers $authHeader
  • Basic Authentication: 虽然 Invoke-WebRequest-Credential 参数用于 Basic Authentication,但手动构建 Authorization 头也是一种方式(虽然不如 -Credential 安全,因为它涉及手动编码)。更推荐使用 -Credential

7. 身份验证

Invoke-WebRequest 提供了专门的参数来处理常见的身份验证机制。

7.1 Basic Authentication

对于 Basic Authentication,你可以使用 -Credential 参数,它接受一个 PSCredential 对象。这样可以避免在脚本中明文存储用户名和密码。

“`powershell

提示用户输入凭据

$credential = Get-Credential “Enter credentials for secure API”

使用凭据发起请求

注意:替换为需要Basic Auth的URL

$secureResponse = Invoke-WebRequest -Uri “https://api.example.com/protected_resource” -Method GET -Credential $credential
“`

Get-Credential cmdlet 会弹出一个图形界面窗口,安全地获取用户名和密码,并将其存储在加密的 PSCredential 对象中。Invoke-WebRequest 会使用这个对象来构建并发送 Basic Authentication 头。

7.2 Windows 集成身份验证 (Kerberos/NTLM)

对于内部网络中需要 Windows 集成身份验证的资源,可以使用 -UseDefaultCredentials 参数。这会使用运行脚本的当前用户的凭据进行身份验证。

“`powershell

注意:替换为需要Windows集成身份验证的内部资源URL

$internalResource = Invoke-WebRequest -Uri “http://internalserver/report.html” -UseDefaultCredentials
“`

7.3 Header-based Authentication

如前所述,对于使用 API 密钥或 Bearer Token 等机制的 API,通常通过在 -Headers 参数中添加 Authorization 或自定义的头来实现。

8. 管理会话和 Cookie

Web 会话(Session)是服务器跟踪用户状态的一种方式,通常通过在客户端和服务器之间交换 Cookie 来实现。例如,登录网站后,服务器会发送一个包含会话ID的Cookie给浏览器,后续请求浏览器会将这个Cookie发送回服务器,从而保持登录状态。

Invoke-WebRequest 提供了 -SessionVariable 参数来管理会话。当你指定 -SessionVariable 参数时,Invoke-WebRequest 会创建一个 DefaultWebProxy 对象(或 WebRequestSession 在PowerShell Core中),并将所有与该会话相关的 Cookie 和其他状态信息存储在这个变量中。后续使用同一个会话变量发起的请求会自动带上之前获取的 Cookie。

示例:模拟登录并访问需要登录的页面

“`powershell

创建一个变量来存储会话

$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession # 或者 просто $null 并让 -SessionVariable 创建

1. 发起登录请求 (假设这是一个POST请求,发送用户名和密码)

$loginUri = “https://example.com/login”
$loginData = @{
username = “myuser”
password = “mypassword”
}

使用 -SessionVariable 参数将登录过程中产生的Cookie存储到 $session 变量中

IWR 会返回响应对象,但更重要的是 $session 变量现在包含了会话状态

$loginResponse = Invoke-WebRequest -Uri $loginUri -Method POST -Body $loginData -SessionVariable session

Write-Host “Login Status Code: $($loginResponse.StatusCode)”

2. 使用同一个会话变量访问需要认证的页面

$protectedPageUri = “https://example.com/myaccount”

再次使用 -SessionVariable $session 参数

IWR 会自动包含之前登录成功后服务器设置的Cookie

$protectedPageResponse = Invoke-WebRequest -Uri $protectedPageUri -Method GET -SessionVariable session

Write-Host “Protected Page Status Code: $($protectedPageResponse.StatusCode)”
Write-Host “Protected Page Content (Snippet): $($protectedPageResponse.Content.Substring(0, 200))”
“`

通过 -SessionVariable 参数,你可以非常方便地模拟用户在网站上的交互流程,例如登录、浏览页面、提交表单等,而无需手动管理 Cookie。

你也可以直接访问 $session 变量来检查或修改 Cookie:

“`powershell

查看当前会话中的所有Cookie (在Windows PowerShell中)

$session.Cookies

查看特定Cookie (在Windows PowerShell中)

$session.Cookies[“sessionid”]

在PowerShell Core中,会话对象可能有不同的结构

例如,可以使用 $session.ProtocolState.CookieContainer

“`

9. 下载文件

Invoke-WebRequest 是一个非常方便的文件下载工具。使用 -OutFile 参数可以将响应内容直接保存到本地文件中,而不是在控制台输出或存储到内存变量的 .Content 属性。

“`powershell
$fileUri = “https://example.com/path/to/somefile.zip”
$outputPath = “C:\temp\downloadedfile.zip”

下载文件

Invoke-WebRequest -Uri $fileUri -OutFile $outputPath

Write-Host “File downloaded to: $outputPath”
“`

使用 -OutFile 时,Invoke-WebRequest 会自动处理文件内容的写入,这对于下载大型文件非常高效,因为它避免了将整个文件内容加载到内存中。

你还可以结合 -StatusCode 来检查下载是否成功:

“`powershell
$fileUri = “https://example.com/path/to/anotherfile.pdf”
$outputPath = “C:\temp\anotherfile.pdf”

使用 -OutFile 参数,但仍然捕获响应对象来检查状态

$downloadResponse = Invoke-WebRequest -Uri $fileUri -OutFile $outputPath

if ($downloadResponse.StatusCode -eq 200) {
Write-Host “File downloaded successfully to: $outputPath”
} else {
Write-Host “File download failed. Status Code: $($downloadResponse.StatusCode)”
# 可选:删除可能已创建的残缺文件
if (Test-Path $outputPath) { Remove-Item $outputPath }
}
“`

10. 错误处理

尽管 Invoke-WebRequest 在遇到 HTTP 错误状态码 (如 404 Not Found, 500 Internal Server Error) 时默认不会抛出终止错误,但检查 StatusCode 是处理这些情况的标准做法。

对于更严重的错误,例如网络连接问题、DNS解析失败、请求超时等,Invoke-WebRequest 会抛出终止错误。你可以使用标准的 PowerShell try...catch 块来捕获这些错误。

“`powershell
$invalidUri = “https://nonexistentdomain123456.com”

try {
$response = Invoke-WebRequest -Uri $invalidUri -TimeoutSec 10 # 设置超时防止无限等待
Write-Host “Request successful. Status: $($response.StatusCode)”
}
catch {
Write-Host “An error occurred during the request:”
Write-Host $_.Exception.Message
}

$errorUri = “https://httpbin.org/status/404” # 一个会返回404的测试服务

try {
$response = Invoke-WebRequest -Uri $errorUri
# 尽管是404,但请求本身成功了,所以不会进入catch块(默认行为)
Write-Host “Request completed. Status Code: $($response.StatusCode)”
if ($response.StatusCode -ge 400) {
Write-Host “HTTP error encountered: $($response.StatusCode)”
# 在这里处理4xx/5xx错误逻辑
}
}
catch {
# 只有连接、超时等终止错误才会到这里
Write-Host “An terminating error occurred: $($_.Exception.Message)”
}
“`

如果你希望 Invoke-WebRequest 在遇到非 2xx 状态码时 抛出 终止错误,以便被 catch 块捕获,可以使用 -SkipStatusCodeCheck反义 (虽然 -SkipStatusCodeCheck 是用来 忽略 状态码检查,使其 抛出错误,默认行为是 抛出,所以你通常不需要额外做什么来让它在非2xx时不抛出错误,除非某些特定版本或配置下行为不同)。

更常见的做法是,请求成功完成(没有网络错误),然后在 try 块内部检查 $response.StatusCode

使用 -ErrorAction Stop 可以强制 Invoke-WebRequest 在遇到任何非终止错误时都停止执行并转换为终止错误,但这通常用于命令本身执行失败的情况,而不是服务器返回的HTTP错误状态码。

11. 高级选项

Invoke-WebRequest 还有一些其他有用的参数:

  • -TimeoutSec <秒>: 设置请求的超时时间(秒)。如果服务器在此时间内没有响应,请求将失败并抛出终止错误。
  • -Proxy <URI>: 指定用于请求的代理服务器。
  • -ProxyCredential <PSCredential>: 为代理服务器提供身份验证凭据。
  • -UserAgent <字符串>: 设置请求的 User-Agent 头。如果你不指定,Invoke-WebRequest 会使用一个默认的 User-Agent 字符串,其中包含 PowerShell 的信息。
  • -MaximumRedirection <整数>: 设置最大重定向次数。默认值为5。
  • -AllowUnencryptedAuthentication: 允许在非HTTPS连接上发送 Basic Authentication 凭据 (警告:非常不安全,应避免使用)。
  • -SkipCertificateCheck: 忽略服务器 SSL/TLS 证书的验证错误 (警告:禁用证书验证会使你容易受到中间人攻击,仅应在受信任的内部环境或开发/测试目的下使用,绝不应在生产环境中对外部网站使用)。
  • -SslProtocol <Protocol>: 指定用于SSL/TLS连接的协议版本(例如 Tls12)。

示例:使用代理和设置超时

“`powershell
$proxyUri = “http://myproxy.example.com:8080”

$proxyCred = Get-Credential “Proxy Credentials” # 如果代理需要认证

try {
$response = Invoke-WebRequest -Uri “https://www.example.com” -Proxy $proxyUri -TimeoutSec 15 #-ProxyCredential $proxyCred
Write-Host “Request via proxy successful. Status: $($response.StatusCode)”
}
catch {
Write-Host “Request via proxy failed:”
Write-Host $_.Exception.Message
}
“`

示例:忽略证书错误 (谨慎使用!)

“`powershell

警告:仅在你知道自己在做什么的情况下使用此选项!

Invoke-WebRequest -Uri “https://internal.untrusted-cert.local” -SkipCertificateCheck
“`

12. Invoke-WebRequest 与 Invoke-RestMethod 的区别

PowerShell 中还有另一个用于 Web 请求的 cmdlet:Invoke-RestMethod (简称 irm)。理解 Invoke-WebRequestInvoke-RestMethod 的区别非常重要,以便选择合适的工具。

Invoke-RestMethod (irm):

  • 专为 REST API 设计: 其主要目的是与 RESTful API 交互。
  • 自动解析响应: 如果服务器返回的 Content-Typeapplication/jsonapplication/xmlInvoke-RestMethod 会自动将响应内容解析为 PowerShell 对象或XML对象,而不是返回原始字符串。这使得访问 API 数据变得非常方便,你可以直接使用点表示法访问 JSON 对象的属性。
  • 简化的输出: 它主要返回解析后的响应体内容,以及一些基本的响应信息(如状态码,可以通过 -ResponseHeadersVariable 获取)。它不像 Invoke-WebRequest 那样提供 ParsedHtmlLinksForms 等与HTML结构相关的属性。
  • 自动处理常见的 API 响应头: 某些情况下,它可能比 Invoke-WebRequest 更智能地处理一些标准的 API 响应头。
  • 默认 User-Agent 不同: 通常会发送一个更简洁的 User-Agent。

Invoke-WebRequest (iwr):

  • 通用 Web 客户端: 它更像是一个命令行浏览器,可以处理各种Web资源,不仅仅是API。
  • 返回结构化对象: 它返回一个 HtmlWebResponseObject (或其他类似的响应对象),其中包含了响应的所有细节:状态码、原始响应头、原始内容、以及可能的 ParsedHtml (在Windows PowerShell中)。
  • 不自动解析 JSON/XML 内容: 你需要手动使用 ConvertFrom-Json[xml] 类型转换来解析 .Content 属性。
  • 提供 HTML 解析功能:ParsedHtml 属性对于简单的网页抓取和交互非常有用(尽管有平台限制)。
  • 提供更详细的原始响应信息: RawContent 属性包含了完整的HTTP交互细节。

何时使用哪一个?

  • 使用 Invoke-RestMethod (irm): 当你确定要与一个 RESTful API 交互,并且期望接收 JSON 或 XML 格式的响应时。这是处理结构化 API 数据的更快捷和便利的方式。
  • 使用 Invoke-WebRequest (iwr): 当你需要:
    • 下载文件 (-OutFile)。
    • 与非 RESTful 服务交互。
    • 获取并处理原始响应头 (.Headers) 或完整的原始响应 (.RawContent)。
    • 需要进行简单的网页抓取,并希望利用 ParsedHtml 对象(主要在 Windows PowerShell 中)。
    • 对请求和响应有更精细的控制,或者处理非标准的响应类型。

在很多情况下,特别是与 REST API 交互时,Invoke-RestMethod 是首选,因为它简化了数据处理。但 Invoke-WebRequest 提供了更全面的底层控制和对HTML的特殊处理能力,使其在其他场景下不可替代。

13. 实践示例:检查网站健康状态

下面是一个综合示例,使用 Invoke-WebRequest 检查多个网站的健康状态:

“`powershell

网站列表

$websites = @(
“https://www.google.com”,
“https://www.microsoft.com”,
“https://www.powershellgallery.com”,
“https://nonexistentdomain123456.com” # 故意设置一个错误域名来测试错误处理
“https://httpbin.org/status/500” # 故意设置一个返回500错误的URL
)

Write-Host “Checking website health…”
Write-Host “—————————————————“

foreach ($uri in $websites) {
$status = “Unknown”
$statusCode = “N/A”
$errorMessage = “”

Write-Host "Checking: $uri" -NoNewline

try {
    # 发起请求,设置超时10秒
    $response = Invoke-WebRequest -Uri $uri -TimeoutSec 10 -ErrorAction Stop # 使用ErrorAction Stop捕获连接等终止错误

    # 如果没有终止错误,检查HTTP状态码
    $statusCode = $response.StatusCode

    if ($statusCode -ge 200 -and $statusCode -lt 300) {
        $status = "Success"
    } elseif ($statusCode -ge 300 -and $statusCode -lt 400) {
        $status = "Redirect ($statusCode)"
    } elseif ($statusCode -ge 400 -and $statusCode -lt 500) {
        $status = "Client Error ($statusCode)"
    } elseif ($statusCode -ge 500) {
        $status = "Server Error ($statusCode)"
    } else {
        $status = "Unexpected Status ($statusCode)"
    }

}
catch {
    # 捕获连接、超时等终止错误
    $status = "Connection Error"
    $errorMessage = $_.Exception.Message
    # 尝试从错误对象中提取更多信息,如果可用
    if ($_.Exception.Response) {
         $statusCode = $_.Exception.Response.StatusCode
         $errorMessage = "HTTP Status Code: $($statusCode) - $($_.Exception.Message)"
    }
}
finally {
    # 无论成功或失败,都输出结果
    if ($errorMessage) {
        Write-Host " [Status: $status] [Code: $statusCode] [Error: $errorMessage]"
    } else {
        Write-Host " [Status: $status] [Code: $statusCode]"
    }
}

}

Write-Host “—————————————————”
Write-Host “Health check complete.”
“`

这个脚本遍历一个URI列表,对每个URI发起 Invoke-WebRequest 请求。它使用 try...catch 来捕获网络连接或超时等终止错误,并在 try 块内部检查 HTTP 状态码来判断请求是否成功以及具体的HTTP错误类型(客户端错误、服务器错误等)。它清晰地展示了如何结合 Invoke-WebRequest 的输出来进行错误判断和状态报告。

14. 总结

Invoke-WebRequest 是 PowerShell 中一个极其重要的 cmdlet,它提供了在命令行环境中进行Web交互的强大能力。通过本文的详细讲解,您应该已经掌握了:

  • 如何发起基本的 GET 请求并理解返回的对象结构。
  • 如何使用 POST、PUT、DELETE 等 HTTP 方法,并发送不同格式的请求体(表单、JSON、XML)。
  • 如何通过 URI 或 -QueryString 发送查询参数。
  • 如何处理响应内容,特别是如何使用 ConvertFrom-Json 解析 JSON 数据,以及在 Windows PowerShell 中利用 ParsedHtml 解析 HTML。
  • 如何发送自定义请求头,包括用于身份验证的头。
  • 如何使用 -Credential-UseDefaultCredentials 进行身份验证。
  • 如何使用 -SessionVariable 管理会话和 Cookie,模拟网站登录等流程。
  • 如何使用 -OutFile 方便地下载文件。
  • 如何结合 try...catch 和检查 StatusCode 进行错误处理。
  • 一些高级选项,如超时、代理、忽略证书等(并了解其风险)。
  • Invoke-WebRequestInvoke-RestMethod 的关键区别,以及何时选择使用哪个 cmdlet。

掌握了 Invoke-WebRequest,您就能够更有效地进行自动化脚本编写、系统管理以及与现代网络服务进行集成。结合 PowerShell 强大的脚本能力,您可以构建出复杂的 Web 交互流程和自动化解决方案。现在,是时候打开您的 PowerShell 控制台,开始实践和探索 Invoke-WebRequest 的更多用途了!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部