PowerShellでwgetを使う方法【Invoke-WebRequest入門】


PowerShellでWebリクエストを使いこなす:Invoke-WebRequest入門(wgetからのステップアップ)

はじめに:Webリクエストの必要性とPowerShellの立ち位置

今日のデジタル世界では、インターネット上のリソースにプログラムでアクセスするタスクは日常茶飯事です。ファイルのダウンロード、Webサイトの情報の取得、APIとの連携など、これらの操作はすべて「Webリクエスト」を通じて行われます。

LinuxやmacOSの世界では、コマンドラインからWebリクエストを行うための標準的なツールとして、古くからwgetcurlが広く使われてきました。これらのコマンドは非常に強力で柔軟性があり、多くのスクリプトや自動化タスクで活躍しています。

一方、MicrosoftのWindows環境、特にシステム管理や自動化の分野で力を発揮するPowerShellでは、これらのUnix系コマンドとは異なる独自のアプローチが採用されています。PowerShellには、Webリクエストを行うための組み込みコマンドレットが用意されており、それが今回詳しく解説するInvoke-WebRequestです。

多くのWindowsユーザーやPowerShell初心者は、Linux/Unixの経験がある場合、PowerShellでどのようにwgetcurlのような操作を行うのかを知りたいと思うでしょう。また、たとえUnix系コマンドの経験がなくても、PowerShellを使ってWebから情報を取得したり、ファイルをダウンロードしたりする方法を学びたいと考えているはずです。

この記事では、PowerShellのInvoke-WebRequestコマンドレットに焦点を当て、それがどのようにWebリクエストを実行するのか、特にwgetのような機能を実現するためにどのように使うのかを、初心者にも分かりやすく詳細に解説します。単なる入門に留まらず、その強力な機能であるWebページの解析能力や、セッション管理、認証、データの送信方法など、幅広い使い方を紹介することで、Invoke-WebRequestを自在に使いこなせるようになることを目指します。

この記事を読むことで、あなたは以下のことを習得できます。

  • Invoke-WebRequestとは何か、そしてなぜPowerShellでWebリクエストにこれを使うのか。
  • 基本的なWebページの取得と表示、ファイルへの保存方法。
  • wgetコマンドの一般的なオプションと、それに対応するInvoke-WebRequestのパラメーター。
  • Invoke-WebRequestの最大の特徴である、取得したHTMLコンテンツの解析方法。
  • REST APIなど、構造化されたデータを扱うための基本的な知識と利用方法。
  • Webセッションを維持して、ログインが必要なサイトなどと連携する方法。
  • POSTリクエストなどでサーバーにデータを送信する方法。
  • エラーハンドリングやタイムアウトの設定方法。
  • Invoke-WebRequestと似ているが用途が異なるInvoke-RestMethodとの違い。

さあ、PowerShellでのWebリクエストの世界へ踏み込みましょう。Invoke-WebRequestの力を借りて、あなたのPowerShellスクリプトの可能性を大きく広げてください。

Invoke-WebRequestとは何か?

Invoke-WebRequest(通常、エイリアスiwrで呼ばれることも多い)は、PowerShell 3.0以降に搭載されたコマンドレットです。その名の通り、「Webリクエストを発行する」ための主要なツールです。

基本的な機能は、指定したURI(Uniform Resource Identifier、Webアドレスのようなもの)に対してHTTP、HTTPS、FTPなどのプロトコルを使ってリクエストを送信し、その応答を受け取ることです。これはwgetcurlが提供する機能の核心と同じです。

しかし、Invoke-WebRequestは単にコンテンツを取得するだけでなく、取得した応答を単なる生データとしてではなく、ある程度構造化されたオブジェクトとして返します。特に、HTMLコンテンツを取得した場合、それを自動的に解析してDOM (Document Object Model) のようなオブジェクトとして利用できるようにする機能は、Invoke-WebRequestの大きな特徴であり、wgetにはない強力な点です。これにより、PowerShellスクリプト内でWebページの内容を簡単にナビゲートし、特定の要素(リンク、画像、フォーム部品など)の情報を抽出したり、操作したりすることが可能になります。

なぜwgetcurlではなくInvoke-WebRequestなのか?

Windows環境、特に最新のWindows 10やWindows 11では、PowerShellだけでなく、curl.exewget.exeといった名前の実行ファイルが標準で含まれている場合があります。しかし、これらはLibcurlやGnuWin32プロジェクトなどの移植版であり、PowerShellコマンドレットとは異なります。

PowerShellスクリプト内でWebリクエストを行う場合、Invoke-WebRequestを使うことにはいくつかの利点があります。

  1. ネイティブなPowerShellオブジェクト: Invoke-WebRequestは応答をPowerShellオブジェクトとして返します。これにより、他のPowerShellコマンドレット(Select-ObjectWhere-ObjectConvertFrom-Jsonなど)とシームレスに連携し、取得したデータを加工・処理するのが容易です。wgetcurlの出力は基本的にテキストであり、PowerShellで扱うには文字列処理や正規表現などに頼る必要があり、複雑になりがちです。
  2. 統合されたエラーハンドリング: PowerShellのエラー処理メカニズム(try/catch-ErrorActionなど)を利用できます。
  3. HTML/XML解析: 前述の通り、取得したHTML/XMLコンテンツを自動的に解析し、オブジェクトとして操作できる機能は非常に強力です。これはスクレイピングや情報抽出のタスクを劇的に簡素化します。
  4. 一貫性: PowerShellの他のコマンドレットと同じ命名規則とパラメータースタイルに従うため、PowerShellの知識体系の中で学びやすく、使いやすいです。
  5. 機能の豊富さ: 基本的な取得だけでなく、セッション管理、認証、様々な形式のデータの送信、プロキシ設定など、Webリクエストに必要な多くの機能が標準でサポートされています。

これらの理由から、PowerShell環境でWebリクエストを扱う際には、外部コマンドであるwgetcurlよりも、組み込みのInvoke-WebRequest(あるいは後述するInvoke-RestMethod)を使うことが推奨されます。

Invoke-WebRequestの基本:Webページの取得と表示

まずは最も基本的な使い方から始めましょう。指定したURLのWebページを取得し、その内容をコンソールに表示する方法です。

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

このコマンドを実行すると、Invoke-WebRequestは指定されたURI (https://example.com/) に対してGETリクエストを送信し、サーバーからの応答を受け取ります。そして、その応答情報をカプセル化したHtmlWebResponseObjectという型のオブジェクトを返します。

コンソールに表示されるのは、このオブジェクトのデフォルト表示であり、通常は以下のようないくつかのプロパティのサマリーが表示されます。

StatusCode : 200
StatusDescription : OK
Content : <!doctype html>
<html>
<head>
<title>Example Domain</title>
... (HTML contentの一部) ...
RawContent : HTTP/1.1 200 OK
... (ヘッダー情報を含む生データ) ...
Forms : {}
Headers : {[Content-Encoding, gzip], [Accept-Ranges, bytes], ...}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : mshtml.HTMLDocumentClass
RelationLink : {}
BaseUri : https://example.com/
AbsoluteUri : https://example.com/
Path : /
Query :
Fragment :
Method : GET
MaximumRedirection : 5

ここで重要なプロパティをいくつか見てみましょう。

  • StatusCode: HTTPステータスコードです (例: 200 OK, 404 Not Found, 500 Internal Server Error)。リクエストが成功したかどうかを確認するのに非常に重要です。
  • StatusDescription: ステータスコードに対応する説明です。
  • Content: サーバーから返された応答の本体(ボディ)のテキストコンテンツです。HTMLページであればHTMLコード、JSONデータであればJSON文字列などが含まれます。
  • RawContent: HTTPヘッダーを含む、応答全体の生データです。
  • Headers: 応答ヘッダーを格納したディクショナリ(ハッシュテーブル)です。ContentTypeContentLengthServerDateなどの情報が含まれます。
  • ParsedHtml: これがInvoke-WebRequestの最大の特徴の一つです。取得したコンテンツがHTMLである場合、これを自動的に解析してDOMオブジェクトとして格納します。このオブジェクトを通じて、HTML要素に簡単にアクセスできます。(詳細は後述)
  • Links, Images, Forms, etc.: ParsedHtmlから自動的に抽出されたリンク (<a>タグ)、画像 (<img>タグ)、フォーム (<form>タグ) など、特定の要素のコレクションです。これも便利な機能です。
  • BaseUri, AbsoluteUri: リクエストしたURIに関する情報です。

デフォルトでは、これらのプロパティの一部のみが表示されますが、取得したオブジェクトを変数に格納すれば、すべてのプロパティにアクセスできます。

powershell
$response = Invoke-WebRequest -Uri "https://example.com/"
$response.StatusCode
$response.Content
$response.Headers.'Content-Type'

$response.Contentを表示すれば、取得したWebページのHTMLコード全体を確認できます。

powershell
$response = Invoke-WebRequest -Uri "https://example.com/"
Write-Host $response.Content

応答をファイルに保存する (-OutFile)

wgetの最も一般的な使い方は、Web上のファイルをローカルディスクにダウンロードすることです。これはInvoke-WebRequestでは-OutFileパラメーターを使って実現します。

powershell
Invoke-WebRequest -Uri "https://www.example.com/path/to/somefile.zip" -OutFile "C:\Downloads\somefile.zip"

このコマンドは、指定されたURLからファイルをダウンロードし、-OutFileで指定されたパスに保存します。存在しないディレクトリを指定した場合はエラーになります。既にファイルが存在する場合は、デフォルトでは上書きされます。

-OutFileパラメーターを使用した場合、Invoke-WebRequestはダウンロードの進行状況を示すプログレスバーを表示することがあります。これは大きなファイルをダウンロードする際に便利です。

重要: -OutFileパラメーターを使用した場合、Invoke-WebRequestは応答のコンテンツをファイルに直接書き込むため、Contentプロパティは空になります。また、ParsedHtmlプロパティも利用できません。これは、ファイル保存とオブジェクトとしての解析は異なる目的のため、リソースを節約するためです。ファイルの内容を後で処理したい場合は、ファイルとして保存した後に別のコマンド(例: Get-Content)で読み込む必要があります。

wget -O <出力ファイル> に相当する操作が、Invoke-WebRequest -Uri <URL> -OutFile <出力ファイル> です。

wgetとの比較:一般的な機能マッピング

wgetユーザーがPowerShellへ移行する際に役立つよう、wgetの一般的なオプションがInvoke-WebRequestでどのように実現されるかを見ていきましょう。

wgetオプション Invoke-WebRequestパラメーター 説明
wget <URL> Invoke-WebRequest -Uri <URL> 指定したURLからコンテンツを取得する(ファイル保存なし)
wget -O <file> <URL> Invoke-WebRequest -Uri <URL> -OutFile <file> 指定したURLからファイルをダウンロードし、指定した名前で保存する
wget -P <dir> <URL> Invoke-WebRequest -Uri <URL> -OutFile (Join-Path <dir> (Split-Path <URL> -Leaf)) 指定したディレクトリに、元のファイル名で保存する(少し複雑)
wget --header 'Name: Value' Invoke-WebRequest -Uri <URL> -Headers @{'Name'='Value'} リクエストヘッダーを追加/変更する
wget --user-agent='Agent String' Invoke-WebRequest -Uri <URL> -UserAgent 'Agent String' User-Agentヘッダーを設定する(または-Headersを使う)
wget --post-data='key=value' Invoke-WebRequest -Uri <URL> -Method POST -Body 'key=value' -ContentType 'application/x-www-form-urlencoded' POSTリクエストでデータを送信する(フォームデータの場合)
wget --limit-rate=<rate> Invoke-WebRequestには直接的なパラメーターはない。PowerShellのネットワーク設定や帯域制御ツールを使用。 ダウンロード速度を制限する
wget --timeout=<seconds> Invoke-WebRequest -Uri <URL> -TimeoutSec <seconds> リクエストのタイムアウト時間を設定する
wget --tries=<number> Invoke-WebRequestには直接的なパラメーターはない。PowerShellスクリプトでループやエラー処理を使って実装する。 リトライ回数を設定する
wget --no-check-certificate Invoke-WebRequest -Uri <URL> -SkipCertificateCheck SSL/TLS証明書の検証をスキップする(非推奨! セキュリティリスクあり)
wget --recursive <URL> Invoke-WebRequestには直接的なパラメーターはない。PowerShellスクリプトでリンクを辿って再帰的に実装する。 Webサイトを再帰的にダウンロードする
wget --level=<depth> (上記同様、スクリプトで実装) 再帰ダウンロードの深さを指定する
wget --cookie='name=value' Invoke-WebRequest -Uri <URL> -Headers @{Cookie='name=value'} または -SessionVariable Cookieを送信する(セッション管理が推奨)
wget --load-cookies=<file> -SessionVariableでセッションオブジェクトを操作して実現可能。 ファイルからCookieを読み込む
wget --save-cookies=<file> -SessionVariableでセッションオブジェクトを取得し、Cookie情報をファイルに保存して実現可能。 Cookieをファイルに保存する
wget --basic-auth Invoke-WebRequest -Uri <URL> -Credential (Get-Credential) -UseBasicParsing HTTP Basic認証を使用する
wget -v Invoke-WebRequest -Uri <URL> -Verbose 詳細な出力(PowerShellの共通パラメーター)
wget --referer=<URL> Invoke-WebRequest -Uri <URL> -Headers @{Referer='<URL>'} Refererヘッダーを設定する
wget --limit-rate=<rate> 直接の機能なし。 帯域幅の制限。
wget --proxy=<URL> Invoke-WebRequest -Uri <URL> -Proxy <URL> プロキシサーバーを使用する。
wget --proxy-user=<user> --proxy-password=<pass> Invoke-WebRequest -Uri <URL> -ProxyCredential (Get-Credential) プロキシ認証を行う。
wget --no-clobber Invoke-WebRequest -Uri <URL> -OutFile <file> -DontUseBasicParsing と存在チェックを組み合わせるか、PowerShell 7+ の -SkipExistingCheck (ただしこれは上書きをスキップするわけではない) 既にファイルが存在する場合にダウンロードしない(要スクリプトでの実装)。
wget -c Invoke-WebRequestには直接的なパラメーターはない。Rangeヘッダーと組み合わせて部分的なダウンロードを試みることは可能だが複雑。 中断されたダウンロードを再開する。

例:指定ディレクトリへの保存

wget -P /tmp/downloads https://example.com/file.txt のように、指定ディレクトリに元のファイル名で保存したい場合、Invoke-WebRequestでは少し工夫が必要です。

“`powershell
$url = “https://www.example.com/path/to/somefile.txt”
$downloadDir = “C:\Temp\Downloads”
$fileName = Split-Path $url -Leaf # URLからファイル名部分を取得
$outputPath = Join-Path $downloadDir $fileName # ディレクトリとファイル名を結合

ダウンロードディレクトリが存在しない場合は作成

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

Invoke-WebRequest -Uri $url -OutFile $outputPath
“`

このように、PowerShellのパス操作コマンドレット (Split-PathJoin-PathTest-PathNew-Item) と組み合わせることで、wget-Pオプションに相当する機能を実現できます。

Invoke-WebRequestの強力な機能:HTML/XML解析

前述したように、Invoke-WebRequestの最もユニークで強力な機能は、取得したHTMLまたはXMLコンテンツを自動的に解析し、操作可能なオブジェクト(ParsedHtmlプロパティ)として提供することです。これにより、WebスクレイピングやHTMLコンテンツからの情報抽出が驚くほど容易になります。

ParsedHtmlプロパティは、内部的にはInternet ExplorerのCOMオブジェクト(MSHTML)を利用してHTMLを解析しています。そのため、基本的にはブラウザのDOMオブジェクトと同じように扱うことができます。

例として、特定のWebページからすべてのリンク(<a>タグ)を抽出してみましょう。

“`powershell
$url = “https://learn.microsoft.com/ja-jp/powershell/”
$response = Invoke-WebRequest -Uri $url

取得した応答オブジェクトのParsedHtmlプロパティにアクセス

$htmlDocument = $response.ParsedHtml

HTMLドキュメント内のすべての’a’タグを取得

$links = $htmlDocument.getElementsByTagName(‘a’)

各リンクのテキストとURL (href属性) を表示

foreach ($link in $links) {
# ‘href’属性が存在するか確認
if ($link.href -ne $null -and $link.href.Length -gt 0) {
Write-Host “Text: $($link.innerText), URL: $($link.href)”
}
}
“`

この例では、以下の手順でリンクを抽出しています。

  1. Invoke-WebRequestでMicrosoft LearnのPowerShellページのHTMLを取得し、$responseに格納します。
  2. $response.ParsedHtmlで解析済みのHTMLドキュメントオブジェクトを取得し、$htmlDocumentに格納します。
  3. $htmlDocument.getElementsByTagName('a')を呼び出して、ドキュメント内のすべての<a>要素のコレクションを取得します。
  4. 取得したリンク要素のコレクションをループ処理し、各要素のinnerTextプロパティ(リンクの表示テキスト)とhrefプロパティ(リンク先のURL)を表示します。

同様の方法で、他の様々なHTML要素にアクセスできます。

  • 特定のIDを持つ要素: $htmlDocument.getElementById('someId')
  • 特定のクラスを持つ要素: $htmlDocument.getElementsByClassName('someClass') (PowerShellのバージョンによっては利用できない場合がある)
  • CSSセレクターを使った要素の取得: $htmlDocument.querySelectorAll('div.content p') (PowerShell 5.1以降)

CSSセレクターは、複雑な要素の指定に非常に便利です。例えば、すべての画像URLを取得するには:

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

CSSセレクターを使ってすべてのタグを取得

$images = $response.ParsedHtml.querySelectorAll(‘img’)

各画像のsrc属性を表示

foreach ($img in $images) {
# ‘src’属性が存在するか確認
if ($img.src -ne $null -and $img.src.Length -gt 0) {
Write-Host “Image URL: $($img.src)”
}
}
“`

注意点:ParsedHtmlの互換性

ParsedHtmlプロパティは、Internet ExplorerのCOMコンポーネントに依存しています。したがって、以下の点に注意が必要です。

  • Windows環境のみ: この機能はWindows上で実行されているPowerShellでのみ利用可能です。LinuxやmacOSで実行されているPowerShell Core (PowerShell 6以降) では、ParsedHtmlプロパティは利用できません(通常は$nullになります)。
  • IEのバージョン: 解析結果は、実行環境にインストールされているInternet Explorerのバージョンや設定に影響される可能性があります。
  • 非標準HTML: 不完全に記述されたHTMLや、JavaScriptによって動的に生成されるコンテンツの解析は苦手な場合があります。

PowerShell Coreやクロスプラットフォーム環境でHTMLを解析したい場合は、.NETのクラス(例: HtmlAgilityPackなどの外部ライブラリをインストールして使用する)を使うか、Invoke-RestMethodと組み合わせてAPIから構造化データを取得するなどの代替手段を検討する必要があります。

JSON/REST APIとの連携

現代のWebサービスは、HTMLページだけでなく、APIを通じてプログラムが扱いやすい構造化されたデータを公開することが一般的です。特にRESTful APIでは、JSON (JavaScript Object Notation) フォーマットが広く使われています。

Invoke-WebRequestは、APIからの応答も取得できます。応答がJSON形式の場合、ContentプロパティにはJSON文字列が含まれます。このJSON文字列をPowerShellオブジェクトに変換するには、ConvertFrom-Jsonコマンドレットを使います。

“`powershell

例:公共のAPIからデータを取得 (例: jsonplaceholder.typicode.com)

$apiUrl = “https://jsonplaceholder.typicode.com/posts/1”
$response = Invoke-WebRequest -Uri $apiUrl

応答が成功したか確認

if ($response.StatusCode -eq 200) {
# Contentプロパティに含まれるJSON文字列をPowerShellオブジェクトに変換
$jsonData = $response.Content | ConvertFrom-Json

# 変換されたオブジェクトのプロパティにアクセス
Write-Host "User ID: $($jsonData.userId)"
Write-Host "Post ID: $($jsonData.id)"
Write-Host "Title: $($jsonData.title)"
Write-Host "Body: $($jsonData.body)"

} else {
Write-Host “APIリクエストに失敗しました。ステータスコード: $($response.StatusCode)”
}
“`

この例では、Invoke-WebRequestでAPIエンドポイントからJSONデータを取得し、$response.ContentにあるJSON文字列をConvertFrom-Jsonにパイプしています。ConvertFrom-Jsonは、JSONデータをPowerShellのカスタムオブジェクト ([PSCustomObject]) やハッシュテーブル、配列などに変換します。これにより、ドット表記 ($jsonData.title) や配列インデックスでデータに簡単にアクセスできるようになります。

APIからの応答がXML形式の場合も同様に、ConvertFrom-Xmlコマンドレットを使ってPowerShellオブジェクトに変換できます。

ただし、APIとの連携が主な目的であれば、後述するInvoke-RestMethodコマンドレットの方が、JSONやXMLを自動的に解析してくれるため、より便利かもしれません。

Webセッションとクッキーの管理 (-SessionVariable)

多くのWebサイトでは、ユーザーの状態を維持するためにクッキー(Cookie)やセッションが利用されます。例えば、ログイン状態を保持したり、ショッピングカートの内容を記憶したりする場合です。wgetでは--save-cookies--load-cookiesオプションを使ってクッキーファイルを管理できますが、Invoke-WebRequestでは-SessionVariableパラメーターを使うことで、より簡単にセッションを管理できます。

-SessionVariableパラメーターは、Webセッションの状態(クッキー、接続設定など)を保持するDefaultWebProxyオブジェクトを格納するための変数を指定します。この変数を後続のInvoke-WebRequestInvoke-RestMethodコマンドレットで再利用することで、同じセッションとしてリクエストを送信できます。

例:ログインが必要なサイトにアクセスする

“`powershell

セッションオブジェクトを格納する変数を指定

$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession

ログインページにアクセスし、ログインフォームの情報を取得

$loginPage = Invoke-WebRequest -Uri “https://example.com/login” -SessionVariable session

ログインフォームを探す (例: 最初のフォームを取得)

$loginForm = $loginPage.Forms[0]

ログインフォームのInputFieldsにユーザー名とパスワードを設定

$loginForm.Fields[“username”] = “YourUsername”
$loginForm.Fields[“password”] = “YourPassword”

設定したフォーム情報を使ってログインリクエストを送信

Submit()メソッドは、フォームのmethod(GET/POST)とaction属性に基づいて自動的にリクエストを作成します。

ここで、-WebSessionパラメーターに前のリクエストで作成したセッションオブジェクトを指定します。

$loggedInPage = Invoke-WebRequest -Uri $loginForm.Action -Method $loginForm.Method -Body $loginForm.Fields -WebSession $session

ログイン後のページの内容を確認

Write-Host $loggedInPage.Content

同じセッションを使って、ログイン後にアクセスできるページにアクセス

$secretPage = Invoke-WebRequest -Uri “https://example.com/members/secretpage” -WebSession $session

Write-Host “— Secret Page Content —”
Write-Host $secretPage.Content
“`

この例のポイントは以下の通りです。

  1. 最初のInvoke-WebRequest-SessionVariable sessionを使用し、$session変数に新しいセッションオブジェクトを作成・格納しています。
  2. 取得したログインページのFormsプロパティを使って、ログインフォームの情報(送信先URL、メソッド、入力フィールドなど)を自動的に取得しています。これはParsedHtml機能の恩恵です。
  3. 取得したフォームオブジェクトのFieldsプロパティ(ハッシュテーブル)に、ユーザー名とパスワードを設定しています。
  4. フォームオブジェクトのSubmit()メソッド(またはInvoke-WebRequestに手動でメソッド、URI、ボディを指定)を使ってログインリクエストを送信します。ここで、-WebSession $sessionを指定することで、最初のアクセスで受け取ったクッキーなどのセッション情報を含めてリクエストが送信されます。
  5. ログイン後のページにアクセスする際も、同じ-WebSession $sessionを指定することで、ログイン状態が維持されたままリクエストが送信されます。

このように、-SessionVariableおよび-WebSessionパラメーターを使うことで、複数のリクエスト間でクッキーや認証状態などのセッション情報を簡単に引き継ぐことができます。これは、ログインが必要なサイトからの情報取得や、連続したAPI呼び出し(認証トークンを使ったアクセスなど)を行う場合に非常に便利です。

サーバーへのデータ送信 (POST, PUTなど)

Invoke-WebRequestは、デフォルトではGETリクエストを送信しますが、-Methodパラメーターを使うことで、POST、PUT、DELETEなどのHTTPメソッドを指定できます。これは、Webフォームの送信や、REST APIを通じてサーバーにデータを送信・更新・削除する際に必要になります。

データを送信するには、-Methodに適切なメソッド(例: POST)を指定し、送信するデータを-Bodyパラメーターで渡します。データの形式に応じて、-ContentTypeパラメーターも設定する必要があります。

フォームデータを送信する (POST)

HTMLフォームを送信する際によく使われる形式はapplication/x-www-form-urlencodedです。-Bodyには、key1=value1&key2=value2のような形式の文字列を渡すか、キーと値をペアにしたハッシュテーブルを渡すことができます。ハッシュテーブルを使った場合、Invoke-WebRequestが自動的にURLエンコードされた文字列に変換してくれます。

“`powershell
$url = “https://example.com/submitform”
$formData = @{
username = “testuser”
password = “testpassword”
submit = “Login”
}

Invoke-WebRequest -Uri $url -Method POST -Body $formData -ContentType ‘application/x-www-form-urlencoded’
“`

または、文字列で直接指定することも可能ですが、手動でのエンコードが必要になる場合があります。

“`powershell
$url = “https://example.com/submitform”
$bodyString = “username=testuser&password=testpassword&submit=Login” # 実際にはURLエンコードが必要な場合が多い

Invoke-WebRequest -Uri $url -Method POST -Body $bodyString -ContentType ‘application/x-www-form-urlencoded’
“`

ParsedHtmlで取得したフォームオブジェクトがあれば、前述のセッションの例のように$loginForm.Fieldsを使って簡単にフォームデータを構築できます。

JSONデータを送信する (POST, PUTなど)

REST APIでは、リクエストのボディとしてJSONデータを送信することが非常に多いです。この場合、-ContentTypeは通常application/jsonに設定し、-BodyにはJSON形式の文字列を渡します。

PowerShellオブジェクト(ハッシュテーブルやカスタムオブジェクト)をJSON文字列に変換するには、ConvertTo-Jsonコマンドレットを使います。

“`powershell
$apiUrl = “https://jsonplaceholder.typicode.com/posts” # 新しい投稿を作成するAPIエンドポイントを想定
$postData = @{
title = “foo”
body = “bar”
userId = 1
}

PowerShellオブジェクトをJSON文字列に変換

$jsonBody = $postData | ConvertTo-Json

Invoke-WebRequest -Uri $apiUrl -Method POST -Body $jsonBody -ContentType ‘application/json’
“`

この例では、PowerShellのハッシュテーブルで送信したいデータを定義し、それをConvertTo-JsonでJSON文字列に変換しています。そのJSON文字列を-Bodyに指定し、-ContentTypeapplication/jsonに設定してPOSTリクエストを送信しています。

APIによっては、XML、FormData (ファイルアップロードを含む multipart/form-data)、またはその他の形式のデータを要求する場合があります。Invoke-WebRequestはこれらの形式にも対応できますが、特にmultipart/form-data(ファイルアップロード)は少し複雑になります。PowerShell 6以降では、-Formパラメーターが追加され、フォームデータ(ファイルアップロードを含む)の送信が容易になりました。

ファイルをアップロードする (multipart/form-data) (PowerShell 6+)

PowerShell 6.0以降では、Invoke-WebRequest-Formパラメーターが追加され、multipart/form-data形式でのデータ送信(ファイルアップロードなど)が簡単になりました。

-Formパラメーターにはハッシュテーブルを渡します。値として文字列や数値だけでなく、[System.IO.FileInfo]オブジェクト(Get-Itemなどで取得)を指定することで、ファイルの内容を送信できます。

“`powershell

アップロードしたいファイルを指定

$filePath = “C:\path\to\yourfile.txt”
$fileInfo = Get-Item $filePath

フォームデータを定義。ファイルはSystem.IO.FileInfoオブジェクトとして指定。

$formData = @{
description = “This is a test file upload.”
file = $fileInfo
someOtherField = “some value”
}

アップロードを受け付けるURL (例)

$uploadUrl = “https://example.com/upload”

Invoke-WebRequest -Uri $uploadUrl -Method POST -Form $formData
“`

-Formパラメーターを使うと、-ContentTypeを明示的に指定する必要はありません。Invoke-WebRequestが自動的にmultipart/form-dataを生成し、適切なバウンダリを設定します。

認証を扱う (-Credential, -UseBasicParsing)

WebサイトやAPIへのアクセスには、認証が必要な場合があります。Invoke-WebRequestは、様々な認証スキームに対応しています。

HTTP Basic認証

ユーザー名とパスワードを使った最もシンプルな認証方式の一つにHTTP Basic認証があります。これは、リクエストヘッダーにユーザー名とパスワードをBase64エンコードした文字列を含めることで行われます。

Invoke-WebRequestでは、-CredentialパラメーターにGet-Credentialコマンドレットで取得した資格情報オブジェクトを指定することで、Basic認証を簡単に設定できます。また、Basic認証を使用する場合は、応答の解析方法をシンプルにするために-UseBasicParsingパラメーターを指定することが推奨されます。

“`powershell

認証が必要なURL

$authUrl = “https://example.com/protected-resource”

ユーザー名とパスワードの入力を求める

$credential = Get-Credential

Basic認証でリクエストを送信

Invoke-WebRequest -Uri $authUrl -Credential $credential -UseBasicParsing
“`

Get-Credentialを実行すると、ユーザー名とパスワードの入力を求めるダイアログが表示されます。入力された情報は暗号化された資格情報オブジェクトとして返され、-Credentialパラメーターに渡されます。

その他の認証方式

Kerberos、Negotiate、NTLMなどの統合Windows認証(Windows Authentication)や、OAuthなどのトークンベース認証など、他の認証方式にも対応しています。統合Windows認証は通常、特別なパラメーターなしで、実行ユーザーの資格情報が自動的に使用されます。OAuthなどのトークン認証は、通常、アクセストークンを-Headersパラメーターを使ってAuthorization: Bearer <token>のような形式で送信することで行います。

“`powershell

OAuth2アクセストークンを使った認証の例

$apiUrl = “https://api.example.com/data”
$accessToken = “your_access_token_here”

$headers = @{
Authorization = “Bearer $accessToken”
}

Invoke-WebRequest -Uri $apiUrl -Headers $headers
“`

エラーハンドリングとステータスコード

Webリクエストは常に成功するとは限りません。ネットワークの問題、サーバー側のエラー、指定したリソースが見つからないなど、様々な原因でエラーが発生する可能性があります。信頼性の高いスクリプトを作成するためには、エラーを適切に処理することが重要です。

Invoke-WebRequestは、HTTPステータスコードを使ってリクエストの結果を示します。前述の通り、応答オブジェクトのStatusCodeプロパティで確認できます。

一般的なHTTPステータスコード:

  • 2xx (Success): リクエストは正常に処理されました (例: 200 OK, 201 Created)。
  • 3xx (Redirection): リクエストを完了するために追加の処理が必要です(リダイレクト)。Invoke-WebRequestはデフォルトでリダイレクトをフォローします。-MaximumRedirectionでフォローする回数を制限できます。
  • 4xx (Client Error): クライアント側のエラー(不正なリクエスト、認証失敗など) (例: 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found)。
  • 5xx (Server Error): サーバー側のエラー (例: 500 Internal Server Error, 503 Service Unavailable)。

Invoke-WebRequestは、デフォルトでは4xxや5xxのようなクライアントまたはサーバーエラーが発生した場合、エラーレコードを生成します。これをPowerShellの標準的なエラー処理メカニズムで捕捉できます。

try/catchブロックを使う

より堅牢なエラー処理のためには、try/catchブロックを使うことが推奨されます。Invoke-WebRequestはデフォルトでHTTPエラーを終端しないエラー(Non-terminating Error)として報告しますが、-ErrorAction Stopパラメーターを併用することで、終端するエラー(Terminating Error)に昇格させ、catchブロックで捕捉できるようになります。

“`powershell
$url = “https://example.com/nonexistent-page” # 存在しないページをリクエスト

try {
$response = Invoke-WebRequest -Uri $url -ErrorAction Stop
Write-Host “リクエスト成功!ステータスコード: $($response.StatusCode)”
} catch {
# $PSCmdlet.ThrowTerminatingError() で発生したエラーを捕捉
Write-Host “エラーが発生しました: $($_.Exception.Message)”

# HTTPエラーの場合、ステータスコードを取得できることがある
if ($_.Exception.Response) {
     $statusCode = [int]$_.Exception.Response.StatusCode # StatusCodeプロパティは列挙型なのでintにキャスト
     Write-Host "HTTPステータスコード: $statusCode"
     Write-Host "エラーの詳細: $($_.Exception.Response.StatusDescription)"
}

}
“`

この例では、存在しないページへのリクエストは404 Not Foundエラーを返します。-ErrorAction Stopを指定しているので、この404応答は終端するエラーとなり、catchブロックが実行されます。catchブロック内では、$_変数を通じてエラーオブジェクトにアクセスできます。$_.Exceptionは発生した例外オブジェクトであり、HTTP関連のエラーの場合、そのResponseプロパティからステータスコードなどの応答情報を取得できます。

タイムアウトの設定 (-TimeoutSec)

ネットワークの遅延やサーバーの応答がない場合、リクエストがいつまでも完了しない可能性があります。これを防ぐために、-TimeoutSecパラメーターでタイムアウト時間を秒単位で指定できます。指定した時間内に応答がない場合、リクエストは中止され、エラーが発生します。

“`powershell

タイムアウトを10秒に設定

try {
$response = Invoke-WebRequest -Uri “http://slow-responding-site.com/” -TimeoutSec 10 -ErrorAction Stop
Write-Host “リクエスト成功!”
} catch {
Write-Host “リクエストがタイムアウトしました、またはエラーが発生しました: $($_.Exception.Message)”
}
“`

デフォルトのタイムアウト値は比較的大きい(PowerShell 5.1で約100秒、PowerShell 7以降で約数分)ため、応答性が重要なタスクでは明示的に設定することを検討してください。

Invoke-RestMethodとの違い

Invoke-WebRequestと非常によく似たコマンドレットにInvoke-RestMethod (irmエイリアス) があります。どちらもWebリクエストを送信しますが、応答の処理方法に違いがあります。

  • Invoke-WebRequest: 応答全体(ヘッダー、ステータスコード、コンテンツなど)をカプセル化したHtmlWebResponseObjectを返します。HTMLコンテンツの場合はParsedHtmlプロパティで解析済みDOMオブジェクトを提供します。生データやヘッダー情報、HTML構造自体に興味がある場合に適しています。
  • Invoke-RestMethod: 応答のコンテンツ本体のみに焦点を当てます。応答のContentTypeヘッダーを見て、コンテンツがJSONやXMLなどの構造化データであれば、それを自動的にPowerShellオブジェクトに変換して返します。ヘッダーやステータスコードなどの応答メタ情報は、デフォルトでは返されません。REST APIなどから構造化データを取得し、そのデータ自体をすぐに扱いたい場合に非常に便利です。

例:同じAPIエンドポイントにInvoke-WebRequestInvoke-RestMethodでアクセスした場合

“`powershell
$apiUrl = “https://jsonplaceholder.typicode.com/posts/1”

Invoke-WebRequest を使う

Write-Host “— Invoke-WebRequest Output —”
$iwrResponse = Invoke-WebRequest -Uri $apiUrl
Write-Host “`$iwrResponse の型: $($iwrResponse.GetType().Name)”
Write-Host “Status Code: $($iwrResponse.StatusCode)”
Write-Host “Content (JSON String): $($iwrResponse.Content)”

$iwrResponse.Content | ConvertFrom-Json のように手動で変換が必要

Invoke-RestMethod を使う

Write-Host “n--- Invoke-RestMethod Output ---"
$irmData = Invoke-RestMethod -Uri $apiUrl
Write-Host "
$irmData の型: $($irmData.GetType().Name)”

StatusCodeなどのメタ情報はデフォルトでは含まれない

Write-Host “User ID: $($irmData.userId)”
Write-Host “Post ID: $($irmData.id)”
Write-Host “Title: $($irmData.title)”

$irmDataは既にPowerShellオブジェクトに変換されている

“`

出力を見ると、Invoke-WebRequestHtmlWebResponseObjectを返し、ContentプロパティにJSON文字列が含まれています。一方、Invoke-RestMethodは応答のJSONを自動的に解析し、[PSCustomObject]のようなPowerShellオブジェクトを直接返していることがわかります。

どちらを使うべきか?

  • HTMLページから情報を抽出したい(スクレイピングしたい): Invoke-WebRequest (ParsedHtmlがあるため)
  • ファイルをダウンロードしたい: Invoke-WebRequest (-OutFileがあるため)
  • 応答ヘッダーやステータスコードを詳細に確認したい: Invoke-WebRequest
  • REST APIからJSONやXMLデータを取得し、そのデータを処理したい: Invoke-RestMethod (自動解析が便利)

多くの場合、API連携ではInvoke-RestMethodの方がコードが簡潔になります。しかし、APIからのエラー応答(例: 400 Bad Requestでエラーの詳細がJSONで返される)を処理する場合など、ステータスコードやヘッダーも確認したい場合は、あえてInvoke-WebRequestを使って応答全体を取得し、ステータスコードを確認してから$response.Content | ConvertFrom-Jsonのように手動でコンテンツを解析する方が柔軟に対応できます。

実践的な使用例

ここでは、Invoke-WebRequestを使ったいくつかの具体的なシナリオを紹介します。

例1:複数のファイルをリストからダウンロードする

ファイルリストが書かれたテキストファイル(例: filelist.txt、各行に1つのURL)があるとし、それに記載されたファイルをすべてダウンロードしたい場合。

“`powershell

ダウンロード元のURLリストファイル

$urlListFile = “C:\Scripts\filelist.txt”

ダウンロード先ディレクトリ

$downloadDir = “C:\Downloads\Bulk”

ダウンロードディレクトリが存在しない場合は作成

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

URLリストファイルを読み込み、各URLに対して処理を実行

Get-Content $urlListFile | ForEach-Object {
$url = $_
$fileName = Split-Path $url -Leaf # URLからファイル名を取得
$outputPath = Join-Path $downloadDir $fileName

Write-Host "Downloading: $url to $outputPath"

try {
    Invoke-WebRequest -Uri $url -OutFile $outputPath -ErrorAction Stop
    Write-Host "Downloaded: $fileName - Success"
} catch {
    Write-Host "Error downloading $fileName from $url: $($_.Exception.Message)"
}

}
“`

このスクリプトは、Get-Contentでファイルリストを読み込み、パイプラインで各URLをForEach-Objectに渡しています。ForEach-Objectブロック内で、各URLからファイル名を抽出し、出力パスを構築し、Invoke-WebRequestでファイルをダウンロードしています。ダウンロードごとにtry/catchを使ってエラーハンドリングも行っています。

例2:Webサイトがオンラインかチェックする

WebサイトがHTTPリクエストに応答するか(つまりオンラインか)を確認したい場合。

“`powershell
$websites = @(
“https://www.google.com/”,
“https://www.microsoft.com/”,
“https://this-site-does-not-exist-hopefully.com/”, # 存在しないサイトの例
“https://www.example.com/”
)

foreach ($site in $websites) {
Write-Host “Checking: $site”
try {
# 応答の内容は不要なので、-Method Headでヘッダー情報のみを取得すると効率が良い場合がある
# ただし、一部のサイトはHEADリクエストをサポートしていない、またはGETと異なる応答を返すため注意
# 安全のため、GETリクエストでステータスコードだけを見るのが一般的
$response = Invoke-WebRequest -Uri $site -Method GET -TimeoutSec 15 -ErrorAction Stop -MaximumRedirection 5

    if ($response.StatusCode -ge 200 -and $response.StatusCode -lt 400) {
        Write-Host "  Status: OK ($($response.StatusCode))"
    } else {
        Write-Host "  Status: Problem ($($response.StatusCode))"
    }

} catch {
    # ネットワークエラー、タイムアウトなど
    Write-Host "  Status: Error ($($_.Exception.Message))"
}

}
“`

この例では、サイトリストをループ処理し、各サイトに対してInvoke-WebRequestを発行しています。-TimeoutSecで応答を待つ時間を制限し、-ErrorAction Stopでエラー発生時に捕捉しています。try/catchブロックの中で、応答のStatusCodeプロパティを確認し、200番台や300番台(リダイレクトも成功とみなす場合)であればOK、それ以外やエラー発生時は問題ありと判断しています。Method HEADはヘッダーのみを取得しますが、サイトによってはGETと同じ応答を返すため、シンプルにGETでステータスコードだけを見る方法がよく使われます。

例3:Webページから特定の情報を抽出する (スクレイピング)

特定のWebページから、例えばすべてのH2見出しとそのテキストを抽出したい場合。

“`powershell
$url = “https://learn.microsoft.com/ja-jp/powershell/” # 例としてMicrosoft Learnのページ
$response = Invoke-WebRequest -Uri $url

ParsedHtmlが利用可能か確認 (Windows PowerShell以外では使えないため)

if ($response.ParsedHtml) {
Write-Host “Searching for H2 elements…”

# CSSセレクターを使ってすべてのh2タグを取得
$h2Elements = $response.ParsedHtml.querySelectorAll('h2')

if ($h2Elements) {
    Write-Host "Found $($h2Elements.Length) H2 elements:"
    foreach ($h2 in $h2Elements) {
        # innerTextプロパティで要素内のテキストを取得
        Write-Host "- $($h2.innerText.Trim())" # Trim()で前後の空白を除去
    }
} else {
    Write-Host "No H2 elements found."
}

} else {
Write-Host “ParsedHtml property is not available. (Are you running on Windows PowerShell?)”
# 代替として、$response.Content を正規表現などで解析することも可能だが複雑になる
}
“`

このスクリプトは、Invoke-WebRequestでページを取得し、ParsedHtmlプロパティを使ってHTMLドキュメントオブジェクトにアクセスしています。querySelectorAll('h2')というCSSセレクターを使って、ドキュメント内のすべての<h2>要素を取得し、それぞれのinnerTextプロパティ(要素内のテキストコンテンツ)を表示しています。ParsedHtml機能が利用できない環境(Linux/macOS上のPowerShell Coreなど)では代替処理が必要な点も示しています。

その他の便利なパラメーター

  • -Headers: カスタムヘッダー(例: RefererOrigin、カスタムAPIキーなど)を追加または上書きします。ハッシュテーブル形式で指定します。
  • -UserAgent: User-Agentヘッダーを設定します。Webサイトによっては、特定のUser-Agentでないとアクセスを拒否したり、異なるコンテンツを返したりすることがあります。デフォルトのUser-AgentはPowerShellのものなので、ブラウザのように見せたい場合などに変更します。
  • -Proxy: プロキシサーバー経由でリクエストを送信します。
  • -ProxyCredential: プロキシ認証が必要な場合に使用します。
  • -MaximumRedirection: リダイレクトをフォローする最大回数を指定します。デフォルトは5回です。リダイレクトループを防ぐのに役立ちます。
  • -AllowUnencrypted: HTTPSの代わりにHTTPを許可するかどうかを指定します。非推奨です。
  • -SkipCertificateCheck: SSL/TLS証明書の検証をスキップします。開発やテスト目的以外では絶対に使用しないでください。中間者攻撃(Man-in-the-Middle attack)のリスクを招きます。
  • -SslProtocol: 使用するSSL/TLSプロトコルバージョンを指定します(例: Tls, Tls12)。古いサイトとの互換性のためや、セキュリティ強化のために使われることがあります。
  • -DisableKeepAlive: 接続を維持せず、リクエストごとに新しい接続を確立します。

パフォーマンスと制限事項

Invoke-WebRequestは非常に便利ですが、大規模なダウンロードや非常に多くの同時リクエストを行う場合には、考慮すべきパフォーマンスや制限事項があります。

  • メモリ使用量: 応答のコンテンツ全体をメモリに読み込んでからオブジェクトとして返すため、非常に大きなファイルをダウンロードする際にメモリを大量に消費する可能性があります。-OutFileパラメーターを使えばメモリ消費は抑えられますが、それでもダウンロード処理自体の効率は専用のダウンロードツールに劣る場合があります。PowerShell 7以降では、大きなファイルのダウンロード性能が改善されています。
  • 速度: シングルスレッドでの処理が基本です。多数のリクエストを並行して処理したい場合は、Start-JobやPowerShellのジョブ機能、またはPowerShell 7以降のForEach-Object -Parallelなどを組み合わせて並列化する必要があります。
  • ParsedHtmlの制約: 前述の通り、IE COMオブジェクトに依存するため、Windows以外で利用できない、JavaScriptで動的に生成されるコンテンツに弱い、などの制約があります。
  • 複雑なWebサイト: CSRFトークン、複雑なJavaScriptによる非同期読み込み、Captchaなど、高度なセキュリティやインタラクションを持つWebサイトのスクレイピングは、Invoke-WebRequestだけでは困難な場合が多いです。Seleniumのようなブラウザ自動化ツールが必要になることがあります。

まとめ:Invoke-WebRequestをマスターする

この記事では、PowerShellでWebリクエストを実行するための主要なコマンドレットであるInvoke-WebRequestについて、その基本的な使い方から、wgetとの比較、HTML/XML解析、セッション管理、データの送信、エラー処理といった応用的な機能まで、幅広く詳細に解説しました。

Invoke-WebRequestは単にファイルをダウンロードするだけでなく、Web応答をPowerShellオブジェクトとして扱い、特にHTMLコンテンツを解析して構造化されたデータとして操作できる強力な能力を持っています。これにより、Webサイトからの情報収集(スクレイピング)、API連携、Webサービスの自動操作など、様々なタスクをPowerShellスクリプト内で効率的に実現できます。

また、応答の自動解析という点ではInvoke-RestMethodという類似のコマンドレットも存在しますが、用途に応じてどちらを使い分けるべきかも理解できたかと思います。HTML解析やファイルダウンロードにはInvoke-WebRequest、REST APIからの構造化データ取得にはInvoke-RestMethodが適しています。

Invoke-WebRequestは非常に多機能なコマンドレットであり、この記事で紹介した内容はすべてではありません。しかし、ここまでの知識があれば、ほとんどの日常的なWebリクエストタスクは十分にこなせるはずです。

PowerShellでのスクリプト作成や自動化において、Web上のリソースとの連携は避けて通れない重要な要素です。ぜひこの記事を参考に、Invoke-WebRequestを積極的に活用し、あなたのPowerShellスキルをさらに向上させてください。実践を通じて様々なパラメーターやシナリオを試してみることで、その真価を理解し、自在に操れるようになるでしょう。

次のステップとして推奨されること:

  • 公式のMicrosoft DocsでInvoke-WebRequestInvoke-RestMethodの最新かつ詳細なドキュメントを参照する。
  • 実際に様々なWebサイトや公開APIに対してInvoke-WebRequestInvoke-RestMethodを実行し、応答オブジェクトのプロパティを調査する。
  • 挑戦的な課題として、特定のWebサイトから特定の情報をスクレイピングするスクリプトを作成してみる。
  • エラー処理やセッション管理を含む、より堅牢なスクリプトを作成してみる。

PowerShellのInvoke-WebRequestは、あなたの自動化やデータ収集のワークフローに不可欠なツールとなるでしょう。自信を持って使い始めてください。


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール