先日、FC2ブログからWordPressへの移行作業を行ったのですが、この時に画像を大量にダウンロードしなければいけなかったため、スクレイピングをする必要が出てきました。
しかし、厄介なことにログインをしなければ目的のページまでたどり着けないようになっているため、単純にURL直打ちでダウンロードすることができませんでした。
認証のためのリクエストを送る方法とかを調べるのが面倒だったので、Chromeをseleniumで動かして、画面のボタン押下で認証を突破していく感じにしました。
その時に実施した内容を備忘録として記載したいと思います。
実現したかったこと
今回やりたかったことは以下になります。
- ログイン画面を開く
- ログイン画面にユーザー名とパスワードを入力してログインボタンを押す
- ログイン後の画面から画像一覧の画面を開く
- 画像一覧の画面にある全ての画像をダウンロードする
上記を実現するために
- seleniumをインストールする
- VBAからseleniumを操作する
ということを実施いたしました。詳細な手順を記載していきたいと思います。
seleniumをインストールする
VBAからはIEはデフォルトで操作することが出来るのですが、もはやIEはサポートも終了しており使う気になりません。
今後のことを考えると、VBAでChromeは操作出来るようにしておいたほうが良いのでseleniumをインストールすることにしました。
seleniumをダウンロードする
以下のページにアクセスし、インストーラーを入手します。
https://github.com/florentbr/SeleniumBasic/releases
このブログの執筆時点では最新バージョンは「v2.0.9.0」になっているので、このバージョンをダウンロードしました。
古いバージョンだと、最新のChromeに対応できないこともあるので、とりあえず一番新しいのを入手しておくのが無難だと思います。
ダウンロードが完了したら、exeファイルを起動してseleniumをインストールします。
自分のChromeバージョンにあったChromeDriverを入手する
Chromeのメニュー(ケバブボタン)から「ヘルプ→GoogleChrome」についてを選択します。
するとChromeのバージョンが表示されます。
次に、そのバージョンに対応したChromeDriverを以下のサイトからダウンロードします。
http://chromedriver.chromium.org/downloads
↓win32という表記が気になったんですが、64bit版でもwin32でOKみたいです
ダウンロードしたChromeDriverをseleniumをインストールしたフォルダに配置します。
デフォルト設定でインストールした場合、C:\Program Files\SeleniumBasicになるかなと思います。
これでseleniumの準備は完了です。
参考にしたサイト
※seleniumのインストールについては、以下のサイトを参考にさせてもらいました。
https://excel-ubara.com/excelvba4/EXCEL_VBA_401.html
VBAでログインと画像ダウンロードを行う
次にVBAのプロジェクト(VBE)を開き、参照設定にSelenium Type Libraryを追加します。
まずはChromeを立ち上げて、ログインを実施するところを実装します。
下調べとして、ログイン画面のHTMLから入力欄やログイン画面のIDを調べます。
今回自分が対象としているサイトでは、ユーザ名を入れる欄が「ID」、パスワードを入れる欄が「pass」というIDになっていました。
そこに値を入れるコードが以下のようになります。
Sub sample()
Dim Driver As New Selenium.WebDriver
Dim myBy As New By
'ログインページを開く
Driver.Start "chrome", "https://admin.blog.fc2.com/control.php?mode=control&process=backup"
Driver.Get "/"
With Driver
'ユーザ名とパスワードを入れてログインボタンを押す
.FindElementById("id").SendKeys "xxxxxxxx@yahoo.co.jp"
.FindElementById("pass").SendKeys "password"
.FindElementByName("image").Click
End With
Driver.Close
Set Driver = Nothing
End Sub
Driver.Start “chrome”の行でサイトのルートを指定し、Driver.Get “/”でそのサイトを開いています。
.FindElementById(“id”)、FindElementById(“pass”)の行でユーザ名とパスワードを入力しています。
今回ログインボタンにIDがふられておらず、代わりにimageという名前がついていたので、FindElementByName(“image”)で要素を取得してクリックしています。
これでログインをすることができました。
次に画像一覧があるページを開いて、画像をダウンロードします。
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As Long)
Public 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 sample()
Dim Driver As New Selenium.WebDriver
Dim myBy As New By
Driver.Start "chrome", "https://admin.blog.fc2.com/control.php?mode=control&process=backup"
Driver.Get "/"
With Driver
.FindElementById("id").SendKeys "xxxxxxxx@yahoo.co.jp"
.FindElementById("pass").SendKeys "password"
.FindElementByName("image").Click
.Get "/control.php?mode=control&process=backup"
'画像一覧のページを開く
.Get "/control.php?mode=control&process=backup&type=file&ext=pict&page=1"
'タグがimgの要素を全て取得する
Set images = .FindElements(myBy.Tag("img"))
For Each Image In images
'画像のURLを取得
src = Image.Attribute("src")
'URLからファイル名を取得
pos = InStrRev(src, "/")
Filename = Mid(src, pos + 1)
'画像ファイルを保存する
Call GetImageFile(CStr(src), "C:\image\" & Filename)
Next
End With
Sleep 10000
Driver.Close
Set Driver = Nothing
End Sub
Sub GetImageFile(ImgName As String, SaveName As String)
Dim SaveFileName As String, DownloadFile As String, Ret As Long
If ImgName = "" Then Exit Sub
SaveFileName = SaveName
DownloadFile = ImgName
Ret = URLDownloadToFile(0, DownloadFile, SaveFileName, 0, 0)
If Ret <> 0 Then
MsgBox "エラーが発生しました"
End If
End Sub
FindElementsメソッドを使用すると、そのページに有る全ての要素を配列で取得できるので、これをforEachで回して全ファイルを取得しました。
画像のダウンロードには、URLDownloadToFileを使用します。
これで無事に画像を全てダウンロードすることができました。
今回の方法ですと、「ログイン画面に値を入力してログイン→ページを開く」という人間が実施する動作と同じことをやっているため、認証やセッションの維持をブラウザにおまかせできるというメリットがあります。
画像認証などがある場合以外であれば、ほぼすべての画面をこの方法でスクレイピングすることができそうです。
(VBAだとバッチ化が難しいので、定期的に取得だと面倒ですが)
コメントを残す