VBA / 使用Excel VBA爬蟲Google搜尋結果

之前曾經用Python爬蟲Google搜尋結果

Py / 透過谷狗大神爬學校地址

最近因為要處理各縣市回傳的報名表

也會需要處理學校名單的地址

這次想試試看用VBA的方式來爬學校地址

備註:剛開始是想用Google Apps Script的UrlFetchApp.fetch

但是測試很久都沒辦法完整抓到網頁資料,之後再看看有沒有其他的方式

透過VBA有兩種方式可以取得網頁資料

第1種是模擬操作網頁瀏覽器

第2種是使用XMLHTTP物件

1.網頁瀏覽器

這個方式跟在Python使用selenium-webdrive一樣

而在VBA如果要使用selenium-webdrive

要安裝SeleniumBasic

然後再下載最新的chromedriver或edgedriver

取代原本SeleniumBasic安裝時的舊版本檔案

要注意的是從Microsoft Edge Driver下載回來的檔案,檔案名稱不是edgedriver

所以要記得手動改名

前置作業完成之後,在VBA引用Selenium Type Library即可

以下是簡易的操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
Public BOT As New WebDriver

Sub WebDriver()
    s = Application.EncodeURL("壯圍國中")
    BOT.Start "edge"
    BOT.Get "https://www.google.com/search?q=" + s
    
    s = BOT.FindElementsByClass("LrzXr")(1).Text
    
    Debug.Print s
    
    Application.Wait (Now + TimeValue("00:00:03"))
    
    BOT.Quit

End Sub

 

透過 WebDriver取得的網頁內容,可以利用FindElementsByClass等方式,利用DOM取得目標資料

由於是爬蟲程式,要避免短時間大量發出網頁要求,所以用 Application.Wait 設定暫停時間

之後想再改成亂數取1~5秒

2.XMLHTTP物件

在這邊要先補充VBA引用物件的方式分為2種

Early Binding 和 Late Binding

Early Binding 就是先在工具->設定引用項目->勾選

之後用 New 物件名稱來建立物件

Late Binding 則是透過CreateObject(物件名稱)

所以1.透過網頁瀏覽器是用Early Binding

下面的程式碼則是 Late Binding

由於透過xmlHttp取得的responseText就只是文字檔

VBA本身也無法解析Html

所以就只能單純分割字串

要再補充的一點

透過這個方式取得的網頁內容是不同於selenium-webdrive取得的網頁內容

selenium-webdrive想要取得的資料是在Class名稱為LrzXr的span裡

而xmlHttp則是在Class名稱為BNeawe tAd8D AP7Wnd的span裡

而且整個網頁內容不只有一個使用BNeawe tAd8D AP7Wnd的標籤

因此在分析網頁內容之後,透過最接近的關鍵字”地址”

作為第一個分割點,然後再以此為起點來取得BNeawe tAd8D AP7Wnd的位置

之後取得在這之後的第一個</span>做為結束點

後續的程式碼也是一樣要加入間隔時間

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Public Sub xmlHttpGoogle()
    s = Application.EncodeURL("壯圍國中")
    
    '使用Microsoft.XMLHTTP物件,傳送網址給對方,然後取回(GET)回傳資料
    Set WinHttpReq = CreateObject("MSXML2.serverXMLHTTP")
    
    'WinHttpReq.Open "GET", myURL, False, "username", "password"
    WinHttpReq.Open "GET", "https://www.google.com/search?q=" + s, False
    WinHttpReq.send
    
    '將回傳資料放到strBody變數
    strBody = WinHttpReq.responseText
    
    '確認回傳的狀態是否正常,200代表正常
    If WinHttpReq.Status = 200 Then
'        Debug.Print strBody
    End If
    
    '分割字串
    '起始位置
    iDocumentId_Start = InStr(1, strBody, "地址")
    iDocumentId_Start = InStr(iDocumentId_Start, strBody, "<span class=" + Chr(34) + "BNeawe tAd8D AP7Wnd" + Chr(34) + ">") + Len("<span class=" + Chr(34) + "BNeawe tAd8D AP7Wnd" + Chr(34) + ">")
    
    '結束位置
    iDocumentId_End = InStr(iDocumentId_Start, strBody, "</span>")
    
    '取出字串
    ss = Mid(strBody, iDocumentId_Start, iDocumentId_End - iDocumentId_Start)
    
    Debug.Print iDocumentId_Start
    Debug.Print iDocumentId_End
    Debug.Print ss
End Sub

 

 

參考資料

SeleniumBasic v2.0.9.0

[vba][vba selenium]vba selenium的安裝與使用

ChromeDriver

Microsoft Edge Driver

[原創] VBA網路爬蟲-XMLHTTP物件

XmlHttpRequest – Http requests in Excel VBA

Creating latebinding approach in vba using selenium