SE(たぶん)の雑感記

一応SEやっている筆者の思ったことを書き連ねます。会計学もやってたので、両方を生かした記事を書きたいと考えています。 でもテーマが定まってない感がすごい。

Powershellで指定したサイトからファイルを一括ダウンロードする

(2017/04/25追記:GitHubへのリンクを張りました。ページ下部参照!)

おはようございます。

すごく間が空きました(;´・ω・)
転職したり、いろいろ忙しかったのです…

そんな事情は置いといて。

最近、いっぱいPDFファイルが公開されているサイトから、ファイルを一気にダウンロードできないものか
考えていたので、Powershellで作りました。

あくまで自分が楽できればいいので、これは引数で受け取れよ、とかはあると思いますが、そこは見逃してください。

.NETの機能は使っていきます。

・元URL指定

$targetUrl = "https://~/index.html";

#起点となるURL
$uri = New-Object System.Uri $targetUrl;

URLは適当に指定してください。
ここでは、System.Uriオブジェクトを作成しておきます。

・保存先指定

$saveDirectoryName = Get-Date -Format "yyyyMMddHHmmss";

$savePath = New-Item $saveDirectoryName -ItemType Directory -Force

Write-Output 出力先
Write-Output $savePath.FullName;

ここは適当で良いと思います。この通りに書くと、スクリプトの直下にフォルダが作成されます。
(正確にはカレントディレクトリかな?) 「サイトのURL + 時間」をフォルダ名にすると、見栄えが良いかも。

・ダウンロード

try{
    #Webページから、PDFへのリンクを取得
    $response = Invoke-WebRequest -Uri $targetUrl
    
    $links = $response.Links | Where-Object {$_.href -like "*.pdf"} | Select-Object -ExpandProperty href

    #個々のファイルダウンロード
    foreach($link in $links){
        #ファイル名抽出
        $fileName = Split-Path $link -Leaf
        
        #保存先作成(フォルダ + ファイル名)
        $outFilePath = Join-Path $savePath $fileName

        #DL対象ファイルのURL取得(Uriの機能で、絶対パスと相対パスをくっつける)
        $downloadUrl = New-Object System.Uri ($uri, $link)
        
        Invoke-WebRequest -Uri $downloadUrl -OutFile $outFilePath
        Write-Output "$fileName をダウンロードしました。"
    }
}catch [System.Net.WebException]{
    $statusCode = $_.Exception.Response.StatusCode;

    Write-Output エラー発生のため、処理を中断します。

    Write-Output "エラーステータス: $statusCode"
}

例外処理は適当です。(あくまで自分が(ry)

ちょっと解説していきます。

$response = Invoke-WebRequest -Uri $targetUrl

Invoke-WebRequestで、Webページ自体を取得します。
認証が必要なサイトなら、-Credentialでもつけてあげましょう。

$links = $response.Links | Where-Object {$_.href -like "*.pdf"} | Select-Object -ExpandProperty href

なんと、Invoke-WebRequestの戻り値のLinksプロパティは、そのサイトのすべてのリンクを返してくれます。
とはいえ、ページ遷移とかは今回いらないので、PDFへのリンクだけになるよう、Where-Objectでフィルタをかけます。別のファイルなら、そのフィルタをかけましょう。
そのあと、さらにhrefだけになるよう、Select-Objectを使います。
ブラウザに表示される文字を使いたい場合は、このSelect-Objectは不要かもしれないです。

ファイル名つけているところは省略します。

$downloadUrl = New-Object System.Uri ($uri, $link)

.NETのSystey.Uriクラスですが、絶対パスURIと文字列の相対パスを渡すと、相対パスが示す絶対パスを返してくれます!(日本語下手)
リンク:MSDNのヘルプ(Uriクラス)

正直、これがないと書くのが面倒です。これを知るまでは、実際のサイトの構成に合わせて、文字列を操作していました。

Invoke-WebRequest -Uri $downloadUrl -OutFile $outFilePath

ファイルのダウンロード操作です。
-OutFileでファイルパスを指定すると、そこにダウンロードしたファイルを作成してくれます。

あとはひたすらループで、ダウンロードしてくれます。

私はこれで、会計基準とかのファイルを一気にダウンロードしました(笑)

何かのご参考になれば。

初めてマークダウンで書いているので、見づらかったらすみません。

p.s. 全文をGitHubに上げて云々やりたい今日この頃。GitHub使い始めたばかりでわからない(´・ω・`) GitHubに上げました!

github.com