前回までの取り組みで、欲しかった機能はほとんど実装した。ただし、まだ無駄な処理が残っているので、若干修正して高速化を図る。すでに日常的に使えるレベルのスクリプトにはなっているので、後は実際に使っていく中で調整していけばよいだろう。
無駄な処理を考える
まず、前回の成果物を確認しておこう。Microsoft Edgeのヘッドレスモードを中心に、ヘッドレスモードでは取得できないコンテンツをcurlで取得するPowerShellスクリプト「netcat.ps1」だ。
#!/usr/bin/env pwsh
#========================================================================
# URLで指定されたリソースを取得
#========================================================================
#========================================================================
# 引数を処理
# -URL url WebリソースのURL
# -Agent agent リクエストで使うエージェントを指定
#========================================================================
Param(
[Parameter(Mandatory=$true)][String]$URL = "",
[String]$Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
)
#========================================================================
# Webリソース取得に利用するアプリケーション
#========================================================================
$msedge='C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
$curl='C:\Windows\System32\curl.exe'
#========================================================================
# Webリソースの種類を取得
#========================================================================
$ContentType=(& $curl --location `
-A $Agent `
-Ss -I `
$URL |
Select-String "^Content-Type:")
#========================================================================
# どの方法でWebリソースを取得するかを判断
#========================================================================
switch -Wildcard ($ContentType)
{
#================================================================
# HTMLコンテンツ: なるべくWebブラウザのヘッドレスモードを使用
#================================================================
'*text/html*' {
#========================================================
# Microsoft Edgeを使って取得
#========================================================
$method='msedge'
}
#================================================================
# それ以外のコンテンツは curl を使って取得
#================================================================
default {
#========================================================
# curlを使って取得
#========================================================
$method='curl'
}
}
#========================================================================
# Webリソースを取得
#========================================================================
switch ($method)
{
#================================================================
# Microsoft Edgeを使って取得
#================================================================
'msedge'
{
$o1='--headless'
$o2='--dump-dom'
$o3='--enable-logging'
$o4='--user-agent="$agent"'
$tmpf=New-TemporaryFile
Start-Process -FilePath $msedge `
-RedirectStandardOutput $tmpf `
-ArgumentList $o1,$o2,$o3,$o4,$URL `
-Wait
Get-Content $tmpf
Remove-Item $tmpf
}
#================================================================
# curl を使って取得
#================================================================
'curl'
{
& $curl --location `
-A $Agent `
-get $URL
}
}
このスクリプトの処理の本質的な部分は、次のようになる。
- curlでWebサーバからレスポンスヘッダを取得し、対象コンテンツの種類を取得する
- 種類がtext/htmlであればMicrosoft Edgeのヘッドレスモードで、それ以外の場合にはcurlでコンテンツを取得する
つまり、Webサーバとの通信が最低でも2回は発生していることになる。場合によってはこの処理は無駄だ。
例えば、URLの最後が「.html」になっていればHTMLだろうし、「.pdf」になっていればPDFだろう。わざわざWebサーバにコンテンツの種類を問い合わせるのは無駄だ。このようにURLからコンテンツの種類が明確にわかる場合には、Webサーバに問い合わせることなく種類を確定するようにする。これでWebサーバへの通信回数を減らすことができるので、処理の高速化を実現できる。