VBAでWeb上のファイル(画像/動画/PDF)をダウンロードする方法【ServerXMLHTTP】

Windows APIのURLDownloadToFile関数を利用すると、指定した URL の画像を簡単にダウンロードできます。ただしこの関数が対応しているのは、いわゆる「固定パス」の URL にある画像ファイルに限られます。そのため、クエリパラメータ(?id=xxx など)が付与された「パラメータ付きURL」の画像には対応していません。そこで本記事では、パラメータ付きURLの画像もダウンロード可能な方法として、ServerXMLHTTPを利用する方法を解説していきます。
この方法は画像に限らず動画やPDF等のファイルのダウンロードにも有効です。
パラメータ付きURL:https://example.com/image.php?id=12345&size=large
ServerXMLHTTPオブジェクト
ServerXMLHTTPは、VBAから利用できる HTTP通信専用のオブジェクト です。このオブジェクトには、リクエストの送信やレスポンスの取得といった機能がひとまとめになっています。これを使うことで、指定したURLにアクセスしてHTMLを文字列として取得したり、アクセス先のデータをバイナリ形式で取得したりと、さまざまな処理を行うことができます。
ServerXMLHTTPオブジェクトはCreateObject関数を使って下記のようにすることで取得できます。
Dim oHTTP As Object
Set oHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
このオブジェクトを使ってHTMLを文字列として取得する場合のサンプルコードは下記の通りです。
指定した URL に対してGETリクエストを送信することで、そのURLが持つ情報を取得できます。
Sub main()
Dim sHTML As String
sHTML = GetHTML("https://www.example.com/")
Debug.Print sHTML
End Sub
Public Function GetHTML(ByVal sURL As String) As String
Dim oHTTP As Object
Set oHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
'GETリクエストを送信
Call oHTTP.Open("GET", sURL, False)
Call oHTTP.setRequestHeader("User-Agent", "Mozilla/5.0")
Call oHTTP.send
'正常に応答があればHTMLを返す
If oHTTP.Status = 200 Then
GetHTML = oHTTP.responseText
Else
GetHTML = "Error: " & oHTTP.Status & " " & oHTTP.statusText
End If
End Function
setRequestHeader を利用することで「このリクエストはどのような環境から送られたものか」といった追加情報を付与できます。特に"User-Agent"を設定しておくと、サーバーに対して「人間がブラウザからアクセスしたときと同じアクセスですよ」と伝えることができます。この指定がない場合、サーバー側で「機械からのアクセス」と判断され、接続を拒否されるケースがあるため、基本的には設定しておくことをおすすめします。(※WinAPIのURLDownloadToFile関数はこの設定ができません)
Web上の画像ダウンロード
ここでは指定したYouTubeのサムネイル画像をファイルとして保存するサンプルコードを紹介します。YouTubeのサムネイルは開発者ツールで確認するとパラメータ付きURになっているため例として取り上げていますが、コード中のURLを変えれば、基本的には他のサイトでも同じように利用できます。
Sub main()
Dim sURL As String
Dim sExt As String
Dim sSaveDirPath As String
Dim sFilePath As String
Dim IsDownloaded As Boolean
sURL = "https://i.ytimg.com/vi/przDcQe6n5o/hq720.jpg?sqp=-oaymwEnCNAFEJQDSFryq4qpAxkIARUAAIhCGAHYAQHiAQoIGBACGAY4AUAB&rs=AOn4CLAioX9ivuCIGyseh44BC59-qb9RYA"
sSaveDirPath = "C:\...\images" '※保存先のフォルダパスに変更
sExt = ".jpg"
If InStr(1, LCase$(sURL), ".png") > 0 Then sExt = ".png"
If InStr(1, LCase$(sURL), ".webp") > 0 Then sExt = ".webp"
sFilePath = sSaveDirPath & "\thumbnail" & sExt
IsDownloaded = DownloadImageFile(sURL, sFilePath)
If IsDownloaded Then
Debug.Print "ダウンロード成功"
Else
Debug.Print "ダウンロード失敗 "
End If
End Sub
'======================================================================
'= ダウンロード
'======================================================================
Private Function DownloadImageFile(ByVal sURL As String, _
ByVal sFilePath As String) As Boolean
Dim oHTTP As Object
Dim oADO As Object
Set oHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
On Error Resume Next
Call oHTTP.Open("GET", sURL, False)
Call oHTTP.setRequestHeader("User-Agent", "Mozilla/5.0")
Call oHTTP.send
If Err.Number <> 0 Then Exit Function
On Error GoTo 0
If oHTTP.Status < 200 Or oHTTP.Status >= 300 Then Exit Function
Set oADO = CreateObject("ADODB.Stream")
With oADO
.Type = 1
Call .Open
Call .Write(oHTTP.responseBody)
Call .SaveToFile(sFilePath, 2)
.Close
End With
DownloadImageFile = True
End Function
上記コード内の下記部分が動画のサムネイル画像となっています。
sURL = "https://i.ytimg.com/vi/przDcQe6n5o/hq720.jpg?sqp=-oaymwEnCNAFEJQDSFryq4qpAxkIARUAAIhCGAHYAQHiAQoIGBACGAY4AUAB&rs=AOn4CLAioX9ivuCIGyseh44BC59-qb9RYA"
対象は下記としており、URLにアクセスすればこの動画のサムネイルであることが確認できます。
コード解説
保存パスの動的生成
保存するディレクトリや名称を決めるために動的にファイルフルパスを生成します。このとき、指定のURLにどの拡張子が含まれているかを確認して保存するファイルの拡張子も決定しています。
sExt = ".jpg"
If InStr(1, LCase$(sURL), ".png") > 0 Then sExt = ".png"
If InStr(1, LCase$(sURL), ".webp") > 0 Then sExt = ".webp"
sFilePath = sSaveDirPath & "\thumbnail" & sExt
ここでは画像ファイルを前提としているので上記のようになっていますが、.mp4や.pdfなどの拡張子も設定すれば動画やPDFファイルの保存も行うことが可能になります。
GETリクエスト
指定のURLにアクセスして情報を取得する場合は、基本的には下記のコードになります。
Call oHTTP.Open("GET", sURL, False)
Call oHTTP.setRequestHeader("User-Agent", "Mozilla/5.0")
Call oHTTP.send
If oHTTP.Status < 200 Or oHTTP.Status >= 300 Then Exit Function
これにより取得した結果がServerXMLHTTPオブジェクト内に格納され、responseTextやresponseBodyで情報を参照することができます。ネットワークの関係や接続先のページが存在しないなどでうまく接続できなかった場合はStatusの値で判定することができます。
正常にアクセスできた場合は200番台の数字が格納されます。この値はHTTPステータスコードといい、一番有名なコードはページが見つからない時の「404」(https://liclog.net/存在しないページ)だと思います。HTTPステータスコードはServerXMLHTTPオブジェクト特有のものではなくどの言語でも共通のものなので、検索すれば各ステータスがどのような状態なのか簡単に確認することができます。
(参考: HTTPステータスコード – Wikipedia )
取得した情報をファイルに変換
指定のURLにアクセスして情報の取得ができたらresponseBodyでアクセス先ページの情報をバイナリデータとして取得することができます。そしてADODB.Streamを使うことで取得したバイナリデータをそのままファイルとして書き出す(変換する)ことができます。
Set oADO = CreateObject("ADODB.Stream")
With oADO
.Type = 1
Call .Open
Call .Write(oHTTP.responseBody)
Call .SaveToFile(sFilePath, 2)
.Close
End With
Type=1はバイナリモードという指定をしており、順にOpenでストリームを開き、Writeで取得したバイナリデータをそのまま書き込み、そしてSaveToFileでファイルとして保存し、Closeでストリームを閉じるという流れになっています。ここは基本的にこの処理になるので定型文となります。








