Functions/Get-Href.ps1

[CmdletBinding()]
param (
  [Parameter(Mandatory)]
  [uri]
  $Uri,

  [Parameter(Mandatory)]
  [string[]]
  $HrefRegexArray,

  [int[][]]
  $HrefIndexesArray,

  [ValidateNotNullOrEmpty()]
  [string]
  $UserAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',

  [string]
  $Referer
)

Write-Host 'スクレイピングを開始します。' -ForegroundColor Cyan

# インデックスの配列の1次元目の大きさを正規表現の配列に合わせ、差の要素は0で埋める
$countDifference = $HrefRegexArray.Count - $HrefIndexesArray.Count

for ($i = 0; $i -lt $countDifference; $i++) {
  $HrefIndexesArray += @(0)
}

if (($HrefIndexesArray[-1].Count -gt 1) -and ($HrefIndexesArray.Count -gt 2)) {
  throw 'hrefのインデックスを指定する配列において、複数の数字を設定できるのは最後の要素だけです。'
}

# スクレイピング
for ($i = 0; $i -lt $HrefRegexArray.Count; $i++) {
  if ($hrefUris) {
    $Uri = $hrefUris[0]
  }

  $HrefRegex = $HrefRegexArray[$i]
  $HrefIndexes = $HrefIndexesArray[$i]

  $htmlDocument = Get-HtmlDocument -Uri $Uri -UserAgent $UserAgent -Referer $Referer

  $hrefArray = $htmlDocument.GetElementsByTagName('a').href

  if (!$hrefArray) {
    throw ('{0}にはhrefが存在しません。' -f $Uri.AbsoluteUri)
  }

  $matchedHrefArray = $hrefArray -Match $HrefRegex

  if (!$matchedHrefArray) {
    Write-Host '======href一覧======' -ForegroundColor Red
    foreach ($href in $hrefArray) {
      Write-Host $href -ForegroundColor Red
    }

    throw ('{0}で正規表現に一致するhrefを取得できませんでした。正規表現が間違っているか、目的のaタグがJavaScriptで動的に生成されている可能性があります。' -f $Uri.AbsoluteUri)
  }

  $hrefUris = @()

  if ($HrefIndexes[0] -eq 0) {
    # 正規表現に一致した全リンクを取得する場合
    foreach ($matchedHref in $matchedHrefArray) {
      $hrefUris += New-Object System.Uri($Uri, $matchedHref)
    }
  }
  else {
    # 正規表現に一致したリンクの内、指定したインデックスのリンクを取得する場合
    foreach ($HrefIndex in $HrefIndexes) {
      $hrefUris += New-Object System.Uri($Uri, $matchedHrefArray[$HrefIndex - 1])
    }
  }

  # 重複を削除
  $hrefUris = $hrefUris | Sort-Object | Get-Unique
}

return $hrefUris

<#
  .SYNOPSIS
  Webページから正規表現をもとにhrefをスクレイピングし、URI型でリンクを取得します。
  .DESCRIPTION
  Webページから正規表現をもとにhrefをスクレイピングし、URI型でリンクを取得します。
  上から何番目のhrefを取得するかを指定することも可能。
  .PARAMETER Uri
  目的のhrefがあるWebページのURIを指定します。
  .PARAMETER HrefRegexArray
  -Uriで指定したアドレスのページからhrefをスクレイピングする為の正規表現を指定します。
  スクレイピングしたURLで更にスクレイピングする場合は配列で指定します。
  .PARAMETER HrefIndexesArray
    正規表現と一致したhrefの内、何番目のものを取得するかを指定します。
    全てのリンクの場合は0
    最後のリンクの場合は-1
    最初のリンクの場合は1
  複数のhrefのインデックスを指定するには整数の配列で指定します。
  スクレイピングしたリンクで更にスクレイピングする場合は整数の配列の配列を指定します。
  ex. @(@(2),@(3,4))とすると、最初のスクレイピングでは-Uriのページで2番目のリンクを取得し、次のスクレイピングでは取得したリンクのページで3番目と4番目のリンクを取得します。
  .PARAMETER UserAgent
  HTTPリクエストの為のユーザエージェントを指定します。
  .PARAMETER Referer
  HTTPリクエストの為のリファラを指定します。
  .INPUTS
  なし
  .OUTPUTS
  System.URI
    取得したURIを配列で返します。
  .EXAMPLE
  PS C:\>Get-Href -Uri 'https://www.gimp.org/downloads/' -HrefRegexArray '//download\.gimp\.org/mirror/pub/gimp/.+/windows/gimp.+setup.*\.exe' -HrefIndexesArray 0
 
  この例では、GIMPのインストーラーのダウンロードリンクを取得します。
  .LINK
 
#>