クローラー

最近、クローラーを作成する必要が出てきた。
というのは、とある卸業者から商品を購入するのですが、商品の取り扱いリストを貰えたものの、在庫の有無はネットショップで確認してくださいとのこと。
APIサービスもないし、DB情報をサクッとくれることもない。
まさか3,000件を毎月手動で調べるのは馬鹿らしい。
ってことで商品ページを巡回し、情報を獲得するクローラーを作成する事となった。

一般的にはcURLを使用するのでしょうが、そこのネットショップはログイン画面にJavaScriptによるチェックシステムがあり、cURLではその壁を乗り越えられない。
なので他の方法をいろいろ模索し、辿り着いたのが・・・

Microsoft Access(VBA)を使って巡回ツールを作るというもの。
なぜVBAかというと意外と便利で、こういう案件もかなりサクッと作成できるからである。

適当に情報を集め以下のコードでIEをハンドリングし、巡回させることにした。

▼フォームを作成し、以下のコードを書く

Option Compare Database
Public objIE As Object 'フォーム内でPublic宣言しておくと使い回しができて便利

'起動ボタンクリック時
Private Sub IEハンドル_Click()
    Call IE_WAKEUP(objIE) 'IE起動
End Sub

'巡回ボタンクリック時
Private Sub 巡回_Click()
    Dim id As Integer
    Dim html As String
    id = 10000
    Do While id < 14000
        objIE.navigate "http://www.******.com/products/detail.php?product_id=" & id
        Call IEWait(objIE)
        html = objIE.Document.body.innerHTML
        Call 解析(html, id)
        id = id + 1
    Loop
End Sub

Sub 解析(html As String, id As Integer)
        '※ここはhtmlソースに対して好きなように記述
        '※RegExpの正規表現を使おう。
        '※例
        Dim re As RegExp
        Dim mc As MatchCollection

        Set re = New RegExp
        
        html = Replace(html, vbLf, "") '改行コードがうざいので置換

        re.Pattern = "<title>(.+?)<\/title>"
        re.Global = False
        Set mc = re.Execute(html)
        If mc.Count > 0 Then タイトル = Trim(mc.Item(0).SubMatches(0))

        '※てな具合に抽出し、DBへ登録していけば良い
End Sub

▼以下は共通モジュールとして記述

'IE起動
Sub IE_WAKEUP(ByRef objIE As Object)
    Set objIE = CreateObject("InternetExplorer.Application")
    objIE.Visible = True
    objIE.navigate "http://www.**************.com"
    Call IEWait(objIE) 'IEを待機
End Sub
'IEを待機
Function IEWait(ByRef objIE As Object)
    Do While objIE.Busy = True Or objIE.readystate <> 4
        DoEvents
    Loop
End Function

解説:
[起動ボタン]をクリックし、IEをハンドリングさせている。
その状態でログイン情報を入力してログイン
そして[巡回ボタン]でクロール開始。
とすることで、セッションを維持したまま巡回が可能。
1つ問題点としては描画のためレスポンスが悪い。
少しでもレスポンスを上げるために、JSをOFFったり、画像を読み込ませなかったりすると良い。

とりあえずエラー処理等は省いているので適宜、追加するべし。

viva