ウェブ上の画像をダウンロードするWindowsAPI関数URLDownloadToFileを使いこなす

スポンサーリンク

ExcelVBAで画像ダウンロードを自動化する手順

仕事で色々なウェブサイトにアップされている複数の画像をダウンロードする必要があり、その手順を自動化するのにどうすればよいかネットで調べていたところ、WindowsAPIのURLDownloadToFileを使う方法を見つけました。

今回はURLDownloadToFileを用いてウエブページの画像やファイルをダウンロードする方法をご紹介します。

WindowsAPIのURLDownloadToFile関数について

WindowsAPIはWindowsで行う処理をプログラム上で実行するために用意されている機能です。
私もほんの数種類しか把握できていないのですが、WindowsAPIには色々な分野にわたり便利な機能がたくさんあります。

導入にはコツが必要で、慣れないと使うハードルが高いのですが、このWindowsAPIはExcelをはじめとするVBAでも使用することができ、使いこなすことでVBA単独では難しい様々な処理をすごく簡単に実行できるようになります。

今回ご紹介するのはWindowsAPIのURLDownloadToFileという関数で、これはウェブサイトからファイル・画像などをダウンロードするための専用の関数です。

(他にもWindowsAPIを用いて表示されているウインドウを取得したり、ボタンをクリックしたり、テキストボックスに文字を入力したりする方法、待ち時間を設定する方法などをご紹介していますので興味あればこちらのカテゴリページから見てみてください。)

スポンサーリンク

VBAでURLDownloadToFile関数を使う事前準備について

VBAでURLDownloadToFile関数を使うためには、実行させるコードにURLDownloadToFile(〇〇)という内容を記載するだけでなく、URLDownloadToFileとはAPIのこの関数ですよというのを事前に登録しておく必要があります。

具体的には宣言セクションに下記の内容を記載します。

Private Declare PtrSafe Function URLDownloadToFile Lib “urlmon” Alias “URLDownloadToFileA” _
(ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, _
ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long

一応ざっくりと説明すると「urlmon」というライブラリファイルに用意されている「URLDownloadToFileA」という関数を「URLDownloadToFile」という名前で使用しますという意味らしいですが、おまじないのようなものなので詳しく意味を把握していなくても問題ありません。

画像のダウンロードに関しては現実的な方法として、対象のページを開くことが多いと思いますので、宣言セクションに下記も併せて記述してSleep関数も使用できるようにしておく方が良いと思います。

#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal ms As LongPtr)
#Else
Private Declare Sub Sleep Lib “kernel32” (ByVal ms As Long)
#End If
End Sub

その他に準備としてIEを用いてウェブページを開いて操作するので、「ツール」→「参照設定」から下記2つのチェックを付けて利用できるようにしましょう。

  • Microsoft HTML Object Library
  • Microsoft Internet Controls
  • URLDownloadToFileの使い方について

    上記のURLDownloadToFileの事前準備をしておけばVBAで使用する自体は簡単です。

    ダウンロードを実行したいプロシージャ内に「URLDownloadToFile(0, ウェブ上のURL, 保存先フォルダ, 0, 0)」と書けばOKです。
    引数は対象ファイルのウェブ上のURL、ダウンロード先のフォルダ名になります。

    あとダウンロードがうまくいった場合、URLDownloadToFile関数は「0」という数字を返すので戻り値を取得できるように下記のように記述するのが一般的だと思います。

  • 戻り値=URLDownloadToFile(0, 対象ファイルウェブ上のURL, 保存先フォルダ, 0, 0)
  • VBA界の権威であるOfficeTANAKAの田中先生もご自身のサイトで記載されていましたが、URLDownloadToFile関数自体の使い方は簡単ですが、ウェブの対象ファイルのURLをどうやって取得してくるかの方がはるかに難しいと思います。

    URLDownloadToFileの実行サンプル

    URLDownloadToFile関数の使い方を各だけではこの関数の使い方や便利さを実感しにくいと思ったので、下記のようにサンプルを考えてみました。

    これはワークシートのA1列に表示されているURLのページに埋め込まれている画像ファイルをすべてデスクトップの「画像」というフォルダに格納するVBAコードになります。

    この方法だと多少強引で無駄も多いのですが、対象サイトの構造をあまり詳しく調べなくても全部の画像データを取得できるので汎用性は高いと思います。

    また特定のファイルだけダウンロードしたい場合にもファイル名の規則などを調べるのにも役立ちます。

    Option Explicit

    #If VBA7 Then
    Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal ms As LongPtr)
    #Else
    Private Declare Sub Sleep Lib “kernel32” (ByVal ms As Long)
    #End If

    Private Declare PtrSafe Function URLDownloadToFile Lib “urlmon” Alias “URLDownloadToFileA” _
    (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, _
    ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long

    Sub IE表示()

    Dim IE As Object
    Set IE = CreateObject(“InternetExplorer.application”)
    IE.Visible = True
    Sleep 1000
    IE.navigate (Cells(1, 1).Text)

    ’ページが表示されるまで待つ
    Dim x
    x = 0
    Do While (IE.Busy Or IE.readyState < READYSTATE_COMPLETE) And x <= 10
    DoEvents
    Sleep 1000
    Loop
    Sleep 1000

    Dim WSH As Object
    Set WSH = CreateObject(“Wscript.Shell”)

    Dim FSO As Object
    Set FSO = CreateObject(“Scripting.FileSystemObject”)

    Dim DesktopPath As String
    DesktopPath = WSH.SpecialFolders(“Desktop”)

    ’ダウンロード先のフォルダがあるか存在確認
    If FSO.FolderExists(DesktopPath & “画像”) = False Then
    ’存在しなければ作成する
    FSO.CreateFolder DesktopPath & “画像”
    End If

    Dim imgSrc As String
    Dim imgName As String
    Dim strPath As String
    Dim lngRes As Long

    Dim txtInput

    Set txtInput = IE.document.getElementsByTagName(“img”)

    For x = 0 To txtInput.Length - 1

    imgSrc = txtInput(x).src
    imgName = Mid(imgSrc, InStrRev(imgSrc, “/”) + 1)

    ’ファイル名に使えない文字列を除外する
    imgName = Replace(Replace(imgName, “:”, “”), “?”, “”)

    ’ダウンロード先のパスを指定する
    strPath = DesktopPath & “画像” & x & “_” & imgName

    ’ウェブ上に格納されているファイル名が拡張子の後に文字列が追加されている場合の処理
    If Left(Right(strPath, 4), 1) <> “.” Then
    ’画像ファイル名に.jpgが含まれているなら
    If InStr(strPath, “.jpg”) <> 0 Then
    strPath = Left(strPath, InStr(strPath, “.jpg”) + 3)
    ’gifに対しての処理
    ElseIf InStr(strPath, “.gif”) <> 0 Then
    strPath = Left(strPath, InStr(strPath, “.gif”) + 3)
    ’pngに対しての処理
    ElseIf InStr(strPath, “.png”) <> 0 Then
    strPath = Left(strPath, InStr(strPath, “.png”) + 3)
    End If

    End If

    ’ファイルのダウンロード実行
    lngRes = URLDownloadToFile(0, imgSrc, strPath, 0, 0)

    ’ワークシートに情報残す
    Cells(x + 1, 2) = x
    Cells(x + 1, 3) = imgSrc
    Cells(x + 1, 4) = imgName
    Cells(x + 1, 5) = lngRes

    ’ダウンロードがうまくいかなかったら色付けする
    If lngRes <> 0 Then
    Range(Cells(x + 1, 2), Cells(x + 1, 5)).Interior.Color = RGB(255, 200, 200)
    End If

    imgSrc = “”
    imgName = “”

    Next x

    IE.Quit

    Set FSO = Nothing
    Set WSH = Nothing
    Set txtInput = Nothing
    Set IE = Nothing

    End Sub

    私は楽天のサイトで商品検索結果が表示されているページで画像を取得するイメージでコードを作りました。

    楽天のサイトの場合、SVG拡張子のロゴなどが大量に含まれていたり、対象ファイル名にWindows上で使用できない文字が含まれているためにダウンロードが進まなかったりしました。
    そのあたりは少しページごとに調整が必要になります。

    あとはダウンロードをする際にJPGのみにするとかPNGのみにするとか特定の文字を含むものにするかなど検討するとムダなダウンロードをせずに済みますので、工夫次第でより便利なコードにできると思います。

    コメント