[英]pull data from website using VBA excel multiple classname
我知道這已被多次詢問,但是沒有看到通過具有相同類名的div和findind標簽循環的明確答案。
我的第一個問題:
如果我有這樣的事情:
<div id="carousel">
<div id="images">
<div class="imageElement">
<img src="img/image1.jpg">
</div>
<div class="imageElement">
<img src="img/image2.jpg">
</div>
<div class="imageElement">
<img src="img/image3.jpg">
</div>
</div>
</div>
所以我想在div“images”中獲取所有img Src以及imageElement類名中的其他內容,並將它們復制到excel中的某些單元格中。
第二個問題:我已經看到了兩種使用VBA提取Web內容的方法,一種是使用IE而另一種是使用瀏覽器之外的代碼。
Private Sub pullData_Click()
Dim x As Long, y As Long
Dim htm As Object
Set htm = CreateObject("htmlFile")
With CreateObject("msxml2.xmlhttp")
.Open "GET", "http://website.html", False
.send
htm.body.innerHTML = .responsetext
End With
End Sub
第二種方式:
Set ie = New InternetExplorer
With ie
.navigate "http://eoddata.com/stockquote/NASDAQ/AAPL.htm"
.Visible = False
While .Busy Or .readyState <> READYSTATE_COMPLETE
DoEvents
Wend
Set objHTML = .document
DoEvents
End With
Set elementONE = objHTML.getElementsByTagName("TD")
For i = 1 To elementONE.Length
elementTWO = elementONE.Item(i).innerText
If elementTWO = "08/10/12" Then
MsgBox (elementONE.Item(i + 1).innerText)
Exit For
End If
Next i
DoEvents
ie.Quit
DoEvents
Set ie = Nothing
哪一個更好,為什么?
所以,如果你能幫助我,我會很感激。
先感謝您。
您的第一個選項通常更可取,因為它比第二個方法快得多,它會直接向Web服務器發送請求並返回響應。 這比自動化Internet Explorer(第二種選擇)更有效率; 自動化IE非常慢,因為你實際上只是瀏覽網站 - 它必然會導致更多的下載,因為它必須加載頁面中的所有資源 - 圖像,腳本,css文件等。它還將在頁面上運行任何Javascript - 所有這些通常都沒有用,你必須等到它完成才能解析頁面。
然而,這是一把雙刃劍 - 雖然慢得多,但如果你不熟悉html請求,自動化Internet Explorer比第一種方法更容易,特別是當動態生成元素或頁面依賴於AJAX時。 當您需要訪問要求您登錄的站點中的數據時,自動化IE也更容易,因為它將為您處理相關的cookie。 這並不是說第一種方法無法完成網頁抓取,而是需要更深入地了解網站技術和網站架構。
第一種方法的更好選擇是使用不同的對象來處理請求和響應,使用WinHTTP庫提供比MSXML庫更多的彈性,並且通常也會自動處理任何cookie。
至於解析數據,在第一種方法中,您使用后期綁定來創建HTML對象(htmlfile),同時這減少了對引用的需求,同時也降低了功能。 例如,當使用后期綁定時,如果用戶安裝了IE9,則會錯過添加的功能,特別是在這種情況下是getElementsByClass名稱功能。
作為第三種選擇(以及我的首選方法):
Dim oHtml As HTMLDocument
Dim oElement As Object
Set oHtml = New HTMLDocument
With CreateObject("WINHTTP.WinHTTPRequest.5.1")
.Open "GET", "http://www.someurl.com", False
.send
oHtml.body.innerHTML = .responseText
End With
For Each oElement In oHtml.getElementsByClassName("imageElement")
Debug.Print oElement.Children(0).src
Next oElement
'IE 8 alternative
'For Each oElement In oHtml.getElementsByTagName("div")
' If oElement.className = "imageElement" Then
' Debug.Print oElement.Children(0).src
' End If
'Next oElement
這將需要一個Microsoft HTML Object Library
的引用設置 - 如果用戶沒有安裝IE9,它將失敗,但這可以處理,並且變得越來越不相關
要將元素打印到單元格替換:
For Each oElement In oHtml.getElementsByClassName("imageElement")
Debug.Print oElement.Children(0).src
Next oElement
附:
Dim wsTarget as Worksheet
dim i as Integer
i=1
set wsTarget=activeworkbook.worksheets("SomeSheet")
For Each oElement In oHtml.getElementsByClassName("imageElement")
wstarget.range("A" & i)=oElement.Children(0).src
i=i+1
Next
'更正了For的語法錯誤
CSS選擇器:
您還可以使用#images img[src^='img/']
的CSS選擇器 。
這表示包含帶有屬性src
標記名img
的images
id的元素,其值以'img/'
開頭。
#
是id; []
屬性; ^
開始於; #images img
, img
內images
。
CSS查詢:
由於將匹配多個元素,因此您將使用document
的.querySelectorAll
方法,然后循環返回的nodeList
的長度。
VBA代碼:
Option Explicit
Public Sub test()
Dim html As HTMLDocument
Set html = New HTMLDocument
With CreateObject("WINHTTP.WinHTTPRequest.5.1")
.Open "GET", "http://www.someurl.com", False
.send
html.body.innerHTML = .responseText
End With
Dim aNodeList As Object, iItem As Long
Set aNodeList = html.querySelectorAll("#images img[src^='img/']")
With ActiveSheet
For iItem = 0 To aNodeList.Length - 1
.Cells(iItem + 1, 1) = aNodeList.item(iItem).innerText
'.Cells(iItem + 1, 1) = aNodeList(iItem).innerText '<== or potentially this syntax
Next iItem
End With
End Sub
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.