PowerShell:ストアアプリのセール情報を取得する
執筆日時:
# スクリプトと同じパスにある StoreApps.txt から URL を読み込む $path = $PSScriptRoot | Join-Path -ChildPath "StoreApps.txt" $urls = (Get-Content $path) -as [string[]] # デバッグ用のサンプル # $urls =@( # "https://www.microsoft.com/ja-jp/store/p/nextgen-reader/9wzdncrfj262" # ) foreach ($url in $urls) { try { $request = Invoke-WebRequest $url # アプリ名を取得 $title = $request.AllElements.FindById("page-title").innerText # ParsedHtml もめっちゃ便利やったぞ! # 例:打消し線の付いた定価タグを取得 $body = $request.ParsedHtml $price_node = $body.getElementsByTagName("s") | where { $_.getAttributeNode("class").Value -eq "srv_saleprice" } # 定価が打ち消されていたらセール中ってこと if ($price_node) { $price = $price_node.innerText # 販売価格(セール価格)の取得 $sales_node = $body.getElementsByTagName("meta") | where { $_.getAttributeNode("itemprop").Value -eq "price" } $sales = "¥{0:#,0}" -f [int]$sales_node.getAttributeNode("content").Value # セール期間を取得 $countdown_node = $body.getElementsByTagName("div") | where { $_.getAttributeNode("class").Value -eq "caption text-muted srv_countdown" } $countdown = $countdown_node.innerText $countdown = $countdown.Replace(" • ", "").Trim() # デバッグに使ってた # [PSCustomObject] @{ # Title = $title; Sales = $sales; # Price = $price; Url = $url # } # 今回は成形したはてな記法テキストを出力 @" * $title <s>$price</s> → <b>$sales</b>($countdown) $url`:embed "@ } } catch { Write-Host $Error[0] $url } finally { $sales_node = $null $sales = $null $price_node = $null $price = $null } }
結果はこんな感じ。
* Nextgen Reader <s>¥200</s> → <b>¥100</b>(¥100 値引き あと 7 日です) https://www.microsoft.com/ja-jp/store/p/nextgen-reader/9wzdncrfj262:embed * Minecraft: Windows 10 Edition <s>¥3,150</s> → <b>¥1,150</b>(¥2,000 値引き あと 17 日です) https://www.microsoft.com/ja-jp/store/p/minecraft-windows-10-edition/9nblggh2jhxj:embed
これをそのまま投稿するとこんな記事になりました。
今日学んだこと
スクリプトのあるフォルダーを取得する
PowerScript v3 以降では
$PSScriptRoot
が利用できる。それ以前だと、ちょっとめんどい(といってもひと手間増える程度だけど
キャストっぽいことをする
型演算子 -as が使える。割と柔軟に使えるみたいだけど、俺みたいな万年初心者には、どこまで柔軟にやってくれるのかよくわかんないのが不安。
$urls = (Get-Content $path) -as [string[]]
失敗すると $null が返る。親戚として -is、-isnot もチェック!
指定したクラスのタグを取得する
たとえば s.srv_saleprice は以下のコードでとれる。
$price_node = $request.ParsedHtml.getElementsByTagName("s") | where { $_.getAttributeNode("class").Value -eq "srv_saleprice" } $price_node.innerText
ちなみに、クラスが"caption text-muted srv_countdown"みたいに複数指定されてるときは"srv_countdown"だけで -eq 判定してもダメ。全体で -eq 評価するか、-match を使う。
まぁ、デフォルトでここまでできるのは便利だけど、それ以上はいろいろめんどいし、そろそろ HtmlAgilityPack でやるかなー。AllElements でとったタグの innerText を読むと改行が飛ぶといった挙動もあまり気に入らない(正規表現でお茶を濁した)。
ヒアドキュメント
@" ヒアドキュメント $url 変数も評価される $url`:embed(はてな記法 "@
変数に“:”が続くとそのまま評価されてしまう。困る場合は、バッククォートでエスケープすればいいみたい。
ちなみに、変数を評価してほしくない場合はシングルクォートでくくる。
はてな記法で PowerShell を構文色分け
コード記法で`ps1`を使う。