PowerShellでWebリクエストを使いこなす:Invoke-WebRequest
入門(wget
からのステップアップ)
はじめに:Webリクエストの必要性とPowerShellの立ち位置
今日のデジタル世界では、インターネット上のリソースにプログラムでアクセスするタスクは日常茶飯事です。ファイルのダウンロード、Webサイトの情報の取得、APIとの連携など、これらの操作はすべて「Webリクエスト」を通じて行われます。
LinuxやmacOSの世界では、コマンドラインからWebリクエストを行うための標準的なツールとして、古くからwget
やcurl
が広く使われてきました。これらのコマンドは非常に強力で柔軟性があり、多くのスクリプトや自動化タスクで活躍しています。
一方、MicrosoftのWindows環境、特にシステム管理や自動化の分野で力を発揮するPowerShellでは、これらのUnix系コマンドとは異なる独自のアプローチが採用されています。PowerShellには、Webリクエストを行うための組み込みコマンドレットが用意されており、それが今回詳しく解説するInvoke-WebRequest
です。
多くのWindowsユーザーやPowerShell初心者は、Linux/Unixの経験がある場合、PowerShellでどのようにwget
やcurl
のような操作を行うのかを知りたいと思うでしょう。また、たとえ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などのプロトコルを使ってリクエストを送信し、その応答を受け取ることです。これはwget
やcurl
が提供する機能の核心と同じです。
しかし、Invoke-WebRequest
は単にコンテンツを取得するだけでなく、取得した応答を単なる生データとしてではなく、ある程度構造化されたオブジェクトとして返します。特に、HTMLコンテンツを取得した場合、それを自動的に解析してDOM (Document Object Model) のようなオブジェクトとして利用できるようにする機能は、Invoke-WebRequest
の大きな特徴であり、wget
にはない強力な点です。これにより、PowerShellスクリプト内でWebページの内容を簡単にナビゲートし、特定の要素(リンク、画像、フォーム部品など)の情報を抽出したり、操作したりすることが可能になります。
なぜwget
やcurl
ではなくInvoke-WebRequest
なのか?
Windows環境、特に最新のWindows 10やWindows 11では、PowerShellだけでなく、curl.exe
やwget.exe
といった名前の実行ファイルが標準で含まれている場合があります。しかし、これらはLibcurlやGnuWin32プロジェクトなどの移植版であり、PowerShellコマンドレットとは異なります。
PowerShellスクリプト内でWebリクエストを行う場合、Invoke-WebRequest
を使うことにはいくつかの利点があります。
- ネイティブなPowerShellオブジェクト:
Invoke-WebRequest
は応答をPowerShellオブジェクトとして返します。これにより、他のPowerShellコマンドレット(Select-Object
、Where-Object
、ConvertFrom-Json
など)とシームレスに連携し、取得したデータを加工・処理するのが容易です。wget
やcurl
の出力は基本的にテキストであり、PowerShellで扱うには文字列処理や正規表現などに頼る必要があり、複雑になりがちです。 - 統合されたエラーハンドリング: PowerShellのエラー処理メカニズム(
try/catch
、-ErrorAction
など)を利用できます。 - HTML/XML解析: 前述の通り、取得したHTML/XMLコンテンツを自動的に解析し、オブジェクトとして操作できる機能は非常に強力です。これはスクレイピングや情報抽出のタスクを劇的に簡素化します。
- 一貫性: PowerShellの他のコマンドレットと同じ命名規則とパラメータースタイルに従うため、PowerShellの知識体系の中で学びやすく、使いやすいです。
- 機能の豊富さ: 基本的な取得だけでなく、セッション管理、認証、様々な形式のデータの送信、プロキシ設定など、Webリクエストに必要な多くの機能が標準でサポートされています。
これらの理由から、PowerShell環境でWebリクエストを扱う際には、外部コマンドであるwget
やcurl
よりも、組み込みの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
: 応答ヘッダーを格納したディクショナリ(ハッシュテーブル)です。ContentType
、ContentLength
、Server
、Date
などの情報が含まれます。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-Path
、Join-Path
、Test-Path
、New-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)”
}
}
“`
この例では、以下の手順でリンクを抽出しています。
Invoke-WebRequest
でMicrosoft LearnのPowerShellページのHTMLを取得し、$responseに格納します。$response.ParsedHtml
で解析済みのHTMLドキュメントオブジェクトを取得し、$htmlDocumentに格納します。$htmlDocument.getElementsByTagName('a')
を呼び出して、ドキュメント内のすべての<a>
要素のコレクションを取得します。- 取得したリンク要素のコレクションをループ処理し、各要素の
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-WebRequest
やInvoke-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
“`
この例のポイントは以下の通りです。
- 最初の
Invoke-WebRequest
で-SessionVariable session
を使用し、$session
変数に新しいセッションオブジェクトを作成・格納しています。 - 取得したログインページの
Forms
プロパティを使って、ログインフォームの情報(送信先URL、メソッド、入力フィールドなど)を自動的に取得しています。これはParsedHtml
機能の恩恵です。 - 取得したフォームオブジェクトの
Fields
プロパティ(ハッシュテーブル)に、ユーザー名とパスワードを設定しています。 - フォームオブジェクトの
Submit()
メソッド(またはInvoke-WebRequest
に手動でメソッド、URI、ボディを指定)を使ってログインリクエストを送信します。ここで、-WebSession $session
を指定することで、最初のアクセスで受け取ったクッキーなどのセッション情報を含めてリクエストが送信されます。 - ログイン後のページにアクセスする際も、同じ
-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
に指定し、-ContentType
をapplication/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-WebRequest
とInvoke-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 の型: $($irmData.GetType().Name)”
$irmData = Invoke-RestMethod -Uri $apiUrl
Write-Host "
StatusCodeなどのメタ情報はデフォルトでは含まれない
Write-Host “User ID: $($irmData.userId)”
Write-Host “Post ID: $($irmData.id)”
Write-Host “Title: $($irmData.title)”
$irmDataは既にPowerShellオブジェクトに変換されている
“`
出力を見ると、Invoke-WebRequest
はHtmlWebResponseObject
を返し、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
: カスタムヘッダー(例:Referer
、Origin
、カスタム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-WebRequest
とInvoke-RestMethod
の最新かつ詳細なドキュメントを参照する。 - 実際に様々なWebサイトや公開APIに対して
Invoke-WebRequest
やInvoke-RestMethod
を実行し、応答オブジェクトのプロパティを調査する。 - 挑戦的な課題として、特定のWebサイトから特定の情報をスクレイピングするスクリプトを作成してみる。
- エラー処理やセッション管理を含む、より堅牢なスクリプトを作成してみる。
PowerShellのInvoke-WebRequest
は、あなたの自動化やデータ収集のワークフローに不可欠なツールとなるでしょう。自信を持って使い始めてください。