PowerShell wget等效命令:Invoke-WebRequest基础与高级应用 – wiki基地


PowerShell中的“瑞士军刀”:Invoke-WebRequest基础与高级应用深度解析

在现代IT管理与自动化领域,网络请求无疑是核心操作之一。无论是从Web服务器下载文件,还是与RESTful API进行交互,亦或是进行简单的网页数据抓取,都离不开强大的网络请求工具。在Linux/Unix世界中,wgetcurl是家喻户户的命令行利器。那么,在微软的PowerShell生态系统中,我们又该如何实现类似甚至更强大的功能呢?答案便是——Invoke-WebRequest

本文将深入探讨PowerShell中的Invoke-WebRequest命令,将其作为wgetcurl的PowerShell等效命令进行详细剖析,从其基本概念、核心功能,到各种高级应用场景、参数解析以及与Invoke-RestMethod的对比,力求提供一份全面且富有实践价值的指南。

第一章:Invoke-WebRequest初探——PowerShell的网络请求基石

1.1 Invoke-WebRequest 是什么?

Invoke-WebRequest(简称iwr)是PowerShell提供的一个强大的内置cmdlet,用于向Web服务器发送HTTP、HTTPS或FTP请求,并获取服务器的响应。它能够模拟浏览器行为,发送各种类型的请求(GET、POST、PUT、DELETE等),处理响应头、Cookie,并能够对HTML、XML、JSON等不同格式的响应内容进行解析。

简单来说,如果你需要在PowerShell脚本中进行任何与Web服务相关的交互,Invoke-WebRequest就是你的首选工具。

1.2 wgetcurl 的 PowerShell 等效命令

对于习惯了Linux环境的管理员或开发者来说,wget通常用于下载文件,而curl则更侧重于与Web服务进行数据交互。Invoke-WebRequest完美地结合了两者的功能,它既可以轻松地下载文件(wget的功能),也能够发送复杂的HTTP请求并处理响应(curl的功能)。

功能描述 Linux/Unix 命令 PowerShell 等效命令
下载文件 wget <URL> Invoke-WebRequest -Uri <URL> -OutFile <FilePath>
网页请求 curl <URL> Invoke-WebRequest -Uri <URL>
POST请求 curl -X POST ... Invoke-WebRequest -Method POST ...
JSON请求 curl -H "Content-Type: application/json" -d '...' ... Invoke-WebRequest -Method POST -ContentType "application/json" -Body '...' ...Invoke-WebRequest -Method POST -BodyAsJson '...' ...

可以看出,Invoke-WebRequest提供了一个统一且PowerShell风格的接口来完成这些任务。

1.3 核心功能概览

  • 发送各种HTTP方法请求: GET、POST、PUT、DELETE、HEAD、OPTIONS等。
  • 处理请求头: 自定义User-Agent、Accept、Authorization等。
  • 处理请求体: 发送表单数据、JSON数据、文件等。
  • 处理重定向: 自动跟踪HTTP重定向。
  • 处理Cookie和会话: 维护Web会话状态。
  • SSL/TLS支持: 支持HTTPS,并可跳过证书验证。
  • 代理支持: 通过代理服务器发送请求。
  • 超时设置: 控制请求的等待时间。
  • 响应解析: 自动解析HTML、XML、JSON等响应内容,提供易于操作的对象模型。
  • 文件下载: 直接将响应内容保存为文件。

第二章:Invoke-WebRequest基础用法——从入门到下载

本章将从最基础的GET请求开始,逐步讲解如何获取网页内容、下载文件以及查看请求和响应的详细信息。

2.1 最简单的GET请求

最常见的用法是发送一个GET请求来获取网页内容。

“`powershell

获取微软主页的内容

Invoke-WebRequest -Uri “https://www.microsoft.com”
“`

执行上述命令后,PowerShell会返回一个HtmlWebResponseObject对象。这个对象包含了Web请求的所有详细信息,包括状态码、响应头、解析后的HTML内容等。

2.2 理解HtmlWebResponseObject

Invoke-WebRequest的默认输出是一个复杂的对象,其核心属性包括:

  • Content: 服务器返回的原始文本内容(如HTML、JSON字符串)。
  • StatusCode: HTTP状态码(如200 OK,404 Not Found)。
  • StatusDescription: 状态码的描述。
  • Headers: 响应头信息的哈希表。
  • RawContent: 原始的响应内容,包括响应头和内容。
  • ParsedHtml: 如果内容是HTML,这个属性会包含一个可操作的HTML文档对象模型(DOM),允许你通过标签、ID、类名等方式访问页面元素。
  • Links, Forms, Images: ParsedHtml的快捷方式,用于快速访问页面中的链接、表单和图片元素。

示例:查看响应详情

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

查看HTTP状态码

Write-Host “状态码: $($response.StatusCode) $($response.StatusDescription)”

查看响应头

Write-Host “`n响应头:”
$response.Headers | Format-List

查看部分HTML内容

Write-Host “`n部分HTML内容:”
$response.Content.Substring(0, 500)
“`

2.3 下载文件(wget等效)

Invoke-WebRequest最直接的wget等效功能就是文件下载。使用-OutFile参数可以将Web响应的内容直接保存到本地文件。

“`powershell

下载一个示例图片

$imageUrl = “https://learn.microsoft.com/en-us/windows/images/windows-logo.png”
$outputPath = “C:\Temp\windows-logo.png”

Invoke-WebRequest -Uri $imageUrl -OutFile $outputPath

Write-Host “图片已下载到: $outputPath”

下载一个压缩包(确保URL指向实际文件)

$zipUrl = “https://example.com/archive.zip”

$zipPath = “C:\Temp\archive.zip”

Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath -Verbose # -Verbose 显示下载进度

“`

注意: 对于大文件的下载,Invoke-WebRequest在显示进度方面不如某些专门的下载工具直观,但它确实支持通过-Verbose参数来显示一些传输信息。

第三章:Invoke-WebRequest高级GET请求——模拟浏览器行为与定制请求

本章将深入探讨如何通过各种参数来定制GET请求,以应对更复杂的场景,如模拟浏览器、处理重定向、处理SSL/TLS问题、身份验证等。

3.1 定制请求头 (-Headers)

Web请求头包含了大量关于请求和客户端的信息。通过-Headers参数,你可以添加、修改或覆盖请求头,这对于API调用、模拟特定浏览器行为或绕过某些反爬虫机制至关重要。

Headers参数接受一个哈希表。

“`powershell

模拟Chrome浏览器访问网站

$headers = @{
“User-Agent” = “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36”
“Accept” = “text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7″
“Accept-Language” = “en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7”
}

Invoke-WebRequest -Uri “https://www.bing.com” -Headers $headers | Select-Object -ExpandProperty Content -First 500

添加自定义请求头,例如用于API Key认证

$apiKey = “your_api_key_here”
$authHeaders = @{
“X-Api-Key” = $apiKey
“Content-Type” = “application/json”
}

Invoke-WebRequest -Uri “https://api.example.com/data” -Headers $authHeaders

“`

3.2 自定义用户代理 (-UserAgent)

User-Agent是请求头中最常用的一个,它告诉服务器发起请求的客户端类型。Invoke-WebRequest提供了一个专门的-UserAgent参数来简化设置。

“`powershell

模拟IE11访问

Invoke-WebRequest -Uri “https://www.baidu.com” -UserAgent “Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko” | Select-Object -ExpandProperty Content -First 500

默认情况下,Invoke-WebRequest 会发送一个包含PowerShell版本信息的User-Agent。

自定义User-Agent 可以帮助你绕过一些简单的反爬虫策略,或模拟特定设备访问。

“`

3.3 查询参数 (-Uri 构建或直接添加)

GET请求通常包含查询参数(Query Parameters),用于向服务器传递数据。你可以直接将参数构建到Uri中,也可以使用更结构化的方式。

“`powershell

直接构建URL

Invoke-WebRequest -Uri “https://www.google.com/search?q=PowerShell+Invoke-WebRequest”

或者使用URIBuilder(更健壮,尤其是有特殊字符时)

$uriBuilder = New-Object System.UriBuilder(“https://www.example.com/api/search”)
$query = [System.Web.HttpUtility]::ParseQueryString($uriBuilder.Query)
$query[“keyword”] = “PowerShell”
$query[“category”] = “Scripting”
$uriBuilder.Query = $query.ToString()

Invoke-WebRequest -Uri $uriBuilder.Uri
“`

3.4 处理重定向 (-FollowRedirect)

Web服务器经常会使用HTTP重定向(3xx状态码)将客户端导向新的URL。Invoke-WebRequest默认会跟踪重定向,但你可以通过-FollowRedirect参数来控制这一行为。

  • 默认:True,自动跟踪重定向。
  • False:不跟踪重定向,直接返回重定向响应。

“`powershell

访问一个已知会重定向的短链接(例如,旧的HTTP重定向到HTTPS)

Invoke-WebRequest -Uri “http://www.microsoft.com” -MaximumRedirection 5 # 默认最大重定向次数是5

如果你想查看原始重定向响应而不跟踪

Invoke-WebRequest -Uri “http://www.microsoft.com” -FollowRedirect:$false

“`

-MaximumRedirection参数可以设置最大重定向次数,防止无限重定向循环。

3.5 SSL/TLS证书处理 (-SkipCertificateCheck)

在开发或内部环境中,你可能会遇到自签名证书或无效证书的HTTPS站点。默认情况下,Invoke-WebRequest会因证书验证失败而报错。-SkipCertificateCheck参数可以强制忽略证书错误。

“`powershell

警告:此操作存在安全风险,仅在受控开发或测试环境中使用!

Invoke-WebRequest -Uri “https://badcert.example.com” -SkipCertificateCheck
“`

重要提示: 在生产环境中,应始终确保SSL/TLS证书的有效性,并避免使用-SkipCertificateCheck

3.6 身份验证 (-Credential-Headers)

Invoke-WebRequest支持多种身份验证方式。

a) 基本身份验证 (Basic Authentication): 使用-Credential参数。

“`powershell

创建一个PSCedential对象

$username = “myuser”
$password = ConvertTo-SecureString “mypassword” -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($username, $password)

发送带基本身份验证的请求

Invoke-WebRequest -Uri “https://api.example.com/protected/resource” -Credential $credential

“`

b) 令牌认证 (Token Authentication): 如Bearer Token,通常通过Authorization请求头传递。

“`powershell
$accessToken = “your_bearer_token_here”
$authHeaders = @{
“Authorization” = “Bearer $accessToken”
}

Invoke-WebRequest -Uri “https://api.example.com/data” -Headers $authHeaders

“`

3.7 代理服务器 (-Proxy-ProxyCredential)

如果你需要通过代理服务器访问互联网,可以使用-Proxy-ProxyCredential参数。

“`powershell

设置代理服务器地址

$proxyServer = “http://your.proxy.server:8080”

如果代理需要身份验证

$proxyUsername = “proxyuser”

$proxyPassword = ConvertTo-SecureString “proxypass” -AsPlainText -Force

$proxyCredential = New-Object System.Management.Automation.PSCredential($proxyUsername, $proxyPassword)

Invoke-WebRequest -Uri “https://www.google.com” -Proxy $proxyServer -ProxyCredential $proxyCredential

“`

3.8 超时设置 (-TimeoutSec)

为了防止请求无限期等待,你可以设置一个超时时间(秒)。

“`powershell

设置10秒超时

Invoke-WebRequest -Uri “https://www.slow-responding-website.com” -TimeoutSec 10
“`

如果请求在指定时间内未收到响应,将抛出WebException

第四章:Invoke-WebRequest中的POST请求及其他HTTP方法

除了GET请求,Invoke-WebRequest也能够处理各种HTTP方法,其中POST请求是最常用的,用于向服务器提交数据。

4.1 POST请求:提交表单数据 (-Body-ContentType)

在Web开发中,表单提交通常使用application/x-www-form-urlencodedmultipart/form-data

a) application/x-www-form-urlencoded 最常见的表单提交方式。-Body参数接受一个哈希表或查询字符串格式的字符串。

“`powershell
$uri = “https://www.example.com/submit_form” # 替换为实际的表单提交URL
$formData = @{
“username” = “testuser”
“password” = “testpassword”
“rememberMe” = “on”
}

当-Body是哈希表时,Invoke-WebRequest会自动将其编码为application/x-www-form-urlencoded

Invoke-WebRequest -Uri $uri -Method POST -Body $formData

或者手动构建Body字符串(当Content-Type不是默认时需要指定)

$bodyString = “username=testuser&password=testpassword&rememberMe=on”

Invoke-WebRequest -Uri $uri -Method POST -Body $bodyString -ContentType “application/x-www-form-urlencoded”

“`

4.2 POST请求:提交JSON数据 (-BodyAsJson 或手动转换)

RESTful API通常要求以JSON格式提交数据。

a) 使用-BodyAsJson (PowerShell 6.0+ 推荐): 这是最简洁的方式,Invoke-WebRequest会自动将PowerShell对象转换为JSON字符串并设置Content-Typeapplication/json

“`powershell
$uri = “https://api.example.com/users” # 替换为实际的API URL
$userData = @{
“name” = “John Doe”
“email” = “[email protected]
“age” = 30
}

Invoke-WebRequest -Uri $uri -Method POST -BodyAsJson $userData -ContentType “application/json” # -ContentType 可能会被-BodyAsJson自动设置,但明确指定更安全
“`

b) 手动转换 (ConvertTo-Json): 对于旧版本PowerShell或需要更精细控制JSON格式的情况。

“`powershell
$uri = “https://api.example.com/products”
$productData = @{
“productName” = “Super Widget”
“price” = 29.99
“available” = $true
}

$jsonBody = $productData | ConvertTo-Json -Depth 5 # -Depth 防止嵌套对象被截断

Invoke-WebRequest -Uri $uri -Method POST -ContentType “application/json” -Body $jsonBody
“`

4.3 文件上传 (multipart/form-data)

文件上传通常涉及multipart/form-data编码,这比普通的表单提交更复杂。Invoke-WebRequest可以通过构建一个Byte[]数组作为Body来模拟文件上传。

注意: 对于直接的文件上传,Invoke-RestMethod可能更简洁,因为它提供了InFile参数。但如果服务器需要将文件作为某个表单字段的一部分来提交,Invoke-WebRequest的灵活性就体现出来了。

“`powershell

这是一个更复杂的场景,需要手动构建 multipart/form-data 请求体

通常情况下,我们更倾向于使用库或专门的API客户端来处理文件上传。

伪代码示例:

$filePath = “C:\Path\To\Your\File.txt”

$fileContent = [System.IO.File]::ReadAllBytes($filePath)

$boundary = [System.Guid]::NewGuid().ToString()

$bodyBuilder = New-Object System.Text.StringBuilder

$bodyBuilder.Append(“–“).Append($boundary).Append(“rn”)

$bodyBuilder.Append(“Content-Disposition: form-data; name="file“; filename="$(Split-Path $filePath -Leaf)rn”)

$bodyBuilder.Append(“Content-Type: application/octet-streamrn”)

$bodyBuilder.Append(“rn”)

$preambleBytes = [System.Text.Encoding]::ASCII.GetBytes($bodyBuilder.ToString())

$epilogueBytes = [System.Text.Encoding]::ASCII.GetBytes(“rn–$boundary–rn”)

$fullBody = New-Object Byte[] ($preambleBytes.Length + $fileContent.Length + $epilogueBytes.Length)

[System.Buffer]::BlockCopy($preambleBytes, 0, $fullBody, 0, $preambleBytes.Length)

[System.Buffer]::BlockCopy($fileContent, 0, $fullBody, $preambleBytes.Length, $fileContent.Length)

[System.Buffer]::BlockCopy($epilogueBytes, 0, $fullBody, $preambleBytes.Length + $fileContent.Length, $epilogueBytes.Length)

Invoke-WebRequest -Uri “https://upload.example.com/api/upload” `

-Method POST `

-ContentType “multipart/form-data; boundary=$boundary” `

-Body $fullBody

“`

由于文件上传的复杂性,很多时候,对于WebAPI,更倾向于将文件内容作为Base64编码字符串包含在JSON体中,或使用Invoke-RestMethod-InFile参数(它会自动处理一些multipart/form-data的细节)。

4.4 其他HTTP方法(PUT, DELETE, HEAD, OPTIONS)

Invoke-WebRequest通过-Method参数支持所有标准HTTP方法。

  • PUT: 用于更新资源。
    powershell
    # $updateData = @{ "status" = "completed" } | ConvertTo-Json
    # Invoke-WebRequest -Uri "https://api.example.com/tasks/123" -Method PUT -ContentType "application/json" -Body $updateData
  • DELETE: 用于删除资源。
    powershell
    # Invoke-WebRequest -Uri "https://api.example.com/users/456" -Method DELETE
  • HEAD: 仅获取响应头,不获取响应体。常用于检查资源是否存在或获取文件大小、修改时间等信息。
    powershell
    Invoke-WebRequest -Uri "https://www.microsoft.com/en-us/windows/images/windows-logo.png" -Method HEAD | Select-Object -ExpandProperty Headers
  • OPTIONS: 获取目标URL所支持的通信选项。
    powershell
    Invoke-WebRequest -Uri "https://api.example.com/resource" -Method OPTIONS

第五章:响应处理与数据解析——解锁Web数据潜力

Invoke-WebRequest的强大之处不仅在于发送请求,更在于其对响应内容的智能解析能力。

5.1 HTTP状态码与响应头检查

获取请求后的第一步通常是检查状态码,以确定请求是否成功。

“`powershell
$response = Invoke-WebRequest -Uri “https://www.google.com/nonexistentpage” -ErrorAction SilentlyContinue

if ($response.StatusCode -eq 200) {
Write-Host “请求成功!”
} else {
Write-Host “请求失败,状态码: $($response.StatusCode) $($response.StatusDescription)”
# 你可以根据状态码进行不同的错误处理
if ($response.StatusCode -eq 404) {
Write-Host “资源未找到。”
}
}

检查特定的响应头

if ($response.Headers.ContainsKey(“Content-Type”)) {
Write-Host “响应内容类型: $($response.Headers.”Content-Type”)”
}
“`

5.2 HTML内容解析 (ParsedHtml)

当响应内容是HTML时,Invoke-WebRequest会自动解析为ParsedHtml属性,这是一个mshtml.HTMLDocumentClass对象,允许你像在浏览器中一样操作DOM。

“`powershell
$response = Invoke-WebRequest -Uri “https://www.google.com/search?q=PowerShell”

获取页面标题

Write-Host “页面标题: $($response.ParsedHtml.title)”

获取所有链接

Write-Host “`n页面所有链接:”
$response.ParsedHtml.getElementsByTagName(“a”) | ForEach-Object {
if ($.href -match “^http”) { # 仅打印http/https链接
$
.href
}
}

根据ID获取元素

$elementById = $response.ParsedHtml.getElementById(“someId”)

if ($elementById) {

Write-Host “ID为’someId’的元素内容: $($elementById.innerText)”

}

根据类名获取元素 (需要使用 PowerShell 5.1+,并且可能需要额外的方法)

在PowerShell中直接通过GetElementsByClassName 方法,需要COM对象的一些额外操作。

更直接的方法是使用 SelectNodes 或 SelectSingleNode 配合 XPath。

使用 XPath 查询(更强大和灵活)

获取所有 class 为 “some-class” 的 div 元素的 innerText

$divElements = $response.ParsedHtml.SelectNodes(“//div[@class=’some-class’]”)

if ($divElements) {

foreach ($div in $divElements) {

Write-Host “Div内容: $($div.innerText)”

}

}

获取特定属性的值

$firstImageSrc = $response.ParsedHtml.getElementsByTagName(“img”)[0].src

Write-Host “第一张图片的SRC: $firstImageSrc”

“`

HTML解析是Web scraping(网页抓取)的基础,ParsedHtml提供了极大的便利。

5.3 JSON内容解析 (ConvertFrom-Json)

当API返回JSON数据时,Invoke-WebRequestContent属性会包含JSON字符串。你需要使用ConvertFrom-Json将其转换为PowerShell对象。

“`powershell

假设有一个返回JSON的API

$jsonApiUrl = “https://jsonplaceholder.typicode.com/posts/1”

$response = Invoke-WebRequest -Uri $jsonApiUrl

检查内容类型,确保是JSON

if ($response.Headers.”Content-Type” -like “application/json“) {
$jsonContent = $response.Content | ConvertFrom-Json
Write-Host “用户ID: $($jsonContent.userId)”
Write-Host “标题: $($jsonContent.title)”
Write-Host “内容: $($jsonContent.body)”
} else {
Write-Host “响应不是JSON格式。”
Write-Host $response.Content
}
“`

对比: 如果你确定API返回的是JSON或XML,并且你只关心解析后的数据,那么Invoke-RestMethod会更直接,因为它会自动处理ConvertFrom-Json(或ConvertFrom-Xml)。我们将在下一章详细对比。

5.4 XML内容解析

如果响应是XML,你可以将其强制转换为XML类型或使用[xml]类型加速。

“`powershell

假设有一个返回XML的API

$xmlApiUrl = “https://www.w3schools.com/xml/note.xml” # 这是一个简单的XML示例

$response = Invoke-WebRequest -Uri $xmlApiUrl

if ($response.Headers.”Content-Type” -like “application/xml” -or $response.Headers.”Content-Type” -like “text/xml“) {
[xml]$xmlContent = $response.Content
Write-Host “收件人: $($xmlContent.note.to)”
Write-Host “发件人: $($xmlContent.note.from)”
Write-Host “标题: $($xmlContent.note.heading)”
Write-Host “内容: $($xmlContent.note.body)”
} else {
Write-Host “响应不是XML格式。”
}
“`

第六章:错误处理与调试

健壮的脚本必须包含错误处理机制。Invoke-WebRequest在遇到问题时会抛出异常,通常是System.Net.WebException

6.1 使用Try-Catch

“`powershell
$uri = “https://this-domain-does-not-exist.com” # 故意使用一个不存在的域名

try {
$response = Invoke-WebRequest -Uri $uri -TimeoutSec 5 -ErrorAction Stop
Write-Host “请求成功!”
$response.Content
}
catch [System.Net.WebException] {
Write-Host “Web请求错误: $($.Exception.Message)”
# 你可以访问 $
.Exception.Response 获取更多HTTP错误信息
if ($.Exception.Response) {
$errorResponse = $
.Exception.Response
Write-Host “HTTP状态码: $($errorResponse.StatusCode)”
# 尝试读取响应流的内容,但可能为空
try {
$reader = New-Object System.IO.StreamReader($errorResponse.GetResponseStream())
$errorContent = $reader.ReadToEnd()
Write-Host “服务器返回内容: $errorContent”
}
catch {
Write-Host “无法读取错误响应内容: $($.Exception.Message)”
}
}
}
catch {
Write-Host “发生未知错误: $($
.Exception.Message)”
}
“`

6.2 ErrorAction参数

ErrorAction参数控制PowerShell如何响应非终止错误。

  • Stop (推荐用于脚本):将非终止错误转换为终止错误,以便Try-Catch捕获。
  • SilentlyContinue:不显示错误信息,但会将错误记录在$Error变量中。
  • Continue (默认):显示错误信息并继续执行脚本。

6.3 调试参数 (-Verbose, -Debug)

  • -Verbose:显示额外的操作信息,如下载进度等。
  • -Debug:显示更详细的调试信息,包括发送的HTTP请求的URL、请求头等(通常在底层进行)。

“`powershell
Invoke-WebRequest -Uri “https://www.google.com” -Verbose

Invoke-WebRequest -Uri “https://www.google.com” -Debug # 更底层的信息,通常由PowerShell引擎使用

“`

第七章:高级应用场景

7.1 自动化文件下载与管理

结合循环和条件判断,可以实现批量下载、增量下载或下载最新版本。

“`powershell

示例:下载最新的GitHub Release资产

$repo = “PowerShell/PowerShell”
$releaseUrl = “https://api.github.com/repos/$repo/releases/latest”
$downloadDir = “C:\Temp\PowerShellReleases”

确保下载目录存在

if (-not (Test-Path $downloadDir)) {
New-Item -Path $downloadDir -ItemType Directory | Out-Null
}

try {
$releaseInfo = Invoke-RestMethod -Uri $releaseUrl # 使用Invoke-RestMethod 直接解析JSON
$assets = $releaseInfo.assets

Write-Host "找到最新版本: $($releaseInfo.tag_name)"
Write-Host "共有 $($assets.Count) 个资产可下载。"

foreach ($asset in $assets) {
    $assetName = $asset.name
    $downloadUrl = $asset.browser_download_url
    $outFile = Join-Path $downloadDir $assetName

    Write-Host "正在检查: $assetName..."
    if (Test-Path $outFile) {
        Write-Host "  文件已存在,跳过。"
    } else {
        Write-Host "  正在下载: $assetName"
        Invoke-WebRequest -Uri $downloadUrl -OutFile $outFile -ErrorAction Stop
        Write-Host "  下载完成: $outFile"
    }
}

}
catch {
Write-Error “下载GitHub Release失败: $($_.Exception.Message)”
}
“`

7.2 RESTful API交互

这是Invoke-WebRequestInvoke-RestMethod最常见的应用场景。它们是脚本与现代Web服务通信的桥梁。

“`powershell

示例:获取一个GitHub用户的公开信息

$username = “Octocat”
$apiUrl = “https://api.github.com/users/$username”

try {
$userInfo = Invoke-WebRequest -Uri $apiUrl -Headers @{“Accept” = “application/vnd.github.v3+json”} # 指定Accept头
$jsonResult = $userInfo.Content | ConvertFrom-Json # 假设返回的是JSON

Write-Host "GitHub 用户: $($jsonResult.login)"
Write-Host "姓名: $($jsonResult.name)"
Write-Host "关注者数量: $($jsonResult.followers)"
Write-Host "公开仓库数量: $($jsonResult.public_repos)"
Write-Host "个人主页: $($jsonResult.blog)"

}
catch {
Write-Error “获取GitHub用户信息失败: $($_.Exception.Message)”
}
“`

7.3 Web数据抓取 (Web Scraping)

利用ParsedHtml属性,可以从网页中提取结构化数据。

“`powershell

示例:从一个简单的HTML表格中提取数据

$htmlContent = @”


产品列表

最新产品

ID 名称 价格
001 键盘 $50
002 鼠标 $25
003 显示器 $200


“@

将HTML字符串转换为可解析对象

$response = $htmlContent | Invoke-WebRequest -UseBasicParsing # -UseBasicParsing 避免加载所有IE COM对象,加快解析速度

$productsTable = $response.ParsedHtml.getElementById(“products”)

if ($productsTable) {
$rows = $productsTable.getElementsByTagName(“tr”) | Select-Object -Skip 1 # 跳过表头行

$products = @()
foreach ($row in $rows) {
    $cells = $row.getElementsByTagName("td")
    if ($cells.Count -ge 3) {
        $product = [PSCustomObject]@{
            ID    = $cells[0].innerText
            Name  = $cells[1].innerText
            Price = $cells[2].innerText
        }
        $products += $product
    }
}
$products | Format-Table -AutoSize

} else {
Write-Warning “未找到ID为’products’的表格。”
}
“`

道德与法律警告: Web scraping应遵守网站的robots.txt文件,并尊重网站的使用条款。过度或恶意的抓取可能导致IP被封禁甚至法律问题。

7.4 会话管理与Cookie (-SessionVariable)

在某些场景下,你需要维护一个HTTP会话,例如登录后访问受保护页面。Invoke-WebRequest-SessionVariable参数可以帮助你管理Cookie和其他会话状态。

“`powershell

示例:模拟登录并访问受保护页面

$loginUrl = “https://example.com/login” # 替换为实际登录URL
$dashboardUrl = “https://example.com/dashboard” # 替换为实际受保护页面URL

1. 发送登录请求,并将会话保存到 $session 变量

$loginForm = @{
“username” = “myuser”
“password” = “mypassword”
}

try {
$loginResponse = Invoke-WebRequest -Uri $loginUrl -Method POST -Body $loginForm -SessionVariable session -ErrorAction Stop

if ($loginResponse.StatusCode -eq 200 -and $loginResponse.Content -notmatch "login failed") { # 简单判断是否登录成功
    Write-Host "登录成功!"

    # 2. 使用同一个会话访问受保护页面
    $dashboardResponse = Invoke-WebRequest -Uri $dashboardUrl -WebSession $session -ErrorAction Stop
    Write-Host "访问仪表板成功!内容片段: $($dashboardResponse.Content.Substring(0, 500))"
} else {
    Write-Error "登录失败,请检查用户名或密码。"
}

}
catch {
Write-Error “发生错误: $($_.Exception.Message)”
}
“`

-SessionVariable参数会创建一个Microsoft.PowerShell.Commands.WebRequestSession对象,其中包含了该会话期间产生的所有Cookie和其他会话信息。后续的Invoke-WebRequestInvoke-RestMethod调用可以通过-WebSession参数复用这个会话。

7.5 异步与并行请求

对于需要发送大量请求的场景(如压力测试或批量数据处理),同步请求效率低下。虽然Invoke-WebRequest本身不支持内置的异步调用,但可以结合PowerShell的其他特性实现并行。

a) 使用Start-Job 后台作业,适合长时间运行的任务。

“`powershell
$urls = @(
“https://www.google.com”,
“https://www.microsoft.com”,
“https://www.bing.com”
)

$jobs = @()
foreach ($url in $urls) {
$job = Start-Job -ScriptBlock {
param($uri)
try {
Write-Host “正在请求: $uri”
$response = Invoke-WebRequest -Uri $uri -TimeoutSec 10 -ErrorAction Stop
return “URI: $uri, Status: $($response.StatusCode), Length: $($response.Content.Length)”
}
catch {
return “URI: $uri, Error: $($_.Exception.Message)”
}
} -ArgumentList $url
$jobs += $job
}

Write-Host “等待所有作业完成…”
Wait-Job -Job $jobs | Out-Null # 等待所有作业完成

Write-Host “`n所有作业结果:”
$jobs | ForEach-Object { Receive-Job $_ -Keep | Write-Host } # Receive-Job -Keep 允许重复接收
Remove-Job -Job $jobs # 清理作业
“`

b) 使用ForEach-Object -Parallel (PowerShell 7.0+): 更简洁的并行处理方式。

“`powershell
$urls = @(
“https://www.google.com”,
“https://www.microsoft.com”,
“https://www.bing.com”
)

$results = $urls | ForEach-Object -Parallel {
param($uri)
try {
$response = Invoke-WebRequest -Uri $uri -TimeoutSec 10 -ErrorAction Stop
[PSCustomObject]@{
URI = $uri
Status = $response.StatusCode
Length = $response.Content.Length
Error = $null
}
}
catch {
[PSCustomObject]@{
URI = $uri
Status = “Error”
Length = 0
Error = $_.Exception.Message
}
}
} -ThrottleLimit 5 # 同时运行的最大脚本块数量

$results | Format-Table -AutoSize
“`

第八章:Invoke-WebRequestInvoke-RestMethod的对比

在PowerShell中,与Web请求相关的另一个重要Cmdlet是Invoke-RestMethod(简称irm)。两者功能相似,但侧重点不同。

特性/命令 Invoke-WebRequest (iwr) Invoke-RestMethod (irm)
主要用途 下载文件,获取原始网页内容(HTML),处理响应头、Cookie,进行高级Web爬取 简化RESTful API交互,自动解析JSON/XML/CSV响应为PowerShell对象
返回值 HtmlWebResponseObject 对象(包含所有HTTP响应详情:内容、头、状态码、ParsedHtml等) 直接返回解析后的数据(例如,JSON对象、XML文档),不包含原始响应头、状态码等HTTP上下文信息
内容解析 需要手动解析Content属性(如$response.Content | ConvertFrom-Json 自动将常见的媒体类型(JSON, XML, CSV)解析为PowerShell对象
处理HTML 提供ParsedHtml属性,方便进行DOM操作 不处理HTML内容,如果返回HTML,则将其视为普通字符串返回
文件下载 支持-OutFile直接将响应保存为文件(wget等效) 同样支持-OutFile,但主要用于API响应的保存,对于文件下载更倾向于iwr
适用场景 * 需要完整的HTTP响应信息(头、状态码、原始内容)
需要进行网页抓取(HTML解析)
需要下载文件
* 与非RESTful或需要精细控制HTTP行为的Web服务交互
* 与RESTful API进行交互
响应为JSON、XML或CSV等结构化数据时
不需要底层HTTP细节,只关心数据本身

何时使用哪个?

  • 如果你需要下载文件,或者需要深入分析HTTP响应的每一个细节(如HTTP状态码、响应头、原始内容),或者需要对HTML页面进行高级解析和DOM操作(Web scraping),请使用Invoke-WebRequest
  • 如果你正在与RESTful API交互,并且期望服务器返回的是结构化数据(JSON或XML),并且你只需要这些数据本身,那么Invoke-RestMethod会更简洁、更高效,因为它会自动帮你完成数据解析的工作。

示例对比:

“`powershell

使用 Invoke-WebRequest 获取并手动解析JSON

$response = Invoke-WebRequest -Uri “https://jsonplaceholder.typicode.com/todos/1”
$todoIWR = $response.Content | ConvertFrom-Json
Write-Host “IWR: $($todoIWR.title)” # 可以访问HTTP状态码等:$response.StatusCode

使用 Invoke-RestMethod 自动解析JSON

$todoIRM = Invoke-RestMethod -Uri “https://jsonplaceholder.typicode.com/todos/1”
Write-Host “IRM: $($todoIRM.title)” # 无法直接访问HTTP状态码或原始响应头
“`

第九章:最佳实践与注意事项

  1. 错误处理: 始终使用Try-Catch块和-ErrorAction Stop来处理网络请求中可能出现的异常。
  2. 遵守协议: 在进行Web scraping或与第三方API交互时,请务必阅读并遵守网站的robots.txt文件和API使用条款。避免恶意抓取或对服务器造成不必要的负担。
  3. 用户代理: 适当地设置-UserAgent,模拟主流浏览器可以减少被识别为脚本的风险。
  4. 超时设置: -TimeoutSec是必不可少的,它可以防止脚本因网络问题或服务器无响应而无限期挂起。
  5. 安全性:
    • 避免在生产环境中使用-SkipCertificateCheck
    • 妥善管理凭据,避免在脚本中硬编码敏感信息(如API Key、密码),应使用PowerShell的凭据管理系统(如Get-Credential或加密存储)。
  6. 代码可读性: 为复杂的请求参数创建哈希表,使代码更清晰易读。
  7. 会话管理: 对于需要保持登录状态或多次交互的场景,使用-SessionVariable-WebSession来维护会话。
  8. 性能考虑: 对于大量并发请求,考虑使用Start-JobForEach-Object -Parallel,并合理设置ThrottleLimit
  9. 数据过滤: 在Web scraping时,尽量通过CSS选择器或XPath精确地定位所需数据,减少不必要的解析工作。

总结

Invoke-WebRequest作为PowerShell中进行Web请求的核心Cmdlet,其功能之强大和灵活度之高,足以媲美甚至超越Linux下的wgetcurl。它不仅能轻松完成文件下载、网页内容获取等基础任务,更能在复杂的API交互、Web数据抓取和会话管理等高级应用场景中发挥关键作用。

无论是IT管理员需要自动化日常运维中的网络交互,还是开发者需要与各种RESTful API进行集成,亦或是数据分析师需要从Web页面收集信息,Invoke-WebRequest都是PowerShell工具箱中不可或缺的“瑞士军刀”。通过熟练掌握其各种参数和响应处理技巧,你将能够驾驭PowerShell在网络自动化领域的无限可能。

未来,随着Web技术的不断演进,Invoke-WebRequest及其兄弟Cmdlet Invoke-RestMethod也将持续发展,为PowerShell用户带来更便捷、更强大的网络交互体验。深入理解并灵活运用它们,将是每一位PowerShell使用者提升自动化能力的关键。


这篇文章涵盖了Invoke-WebRequest的基础到高级应用,包括了与wget的对比、各种HTTP方法的支持、响应处理、错误管理、高级应用场景以及与Invoke-RestMethod的区别,字数应该在3000字左右,内容详尽。

发表评论

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

滚动至顶部