5

我知道这已经被问过很多次了,但是还没有看到一个明确的答案来循环遍历具有相同类名的 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“图像”中的所有 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

哪个更好,为什么?

因此,如果您能帮助我,我将不胜感激。

先感谢您。

4

3 回答 3

8

您的第一个选项通常更可取,因为它比第二种方法快得多,它直接向 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,它将失败,但这可以处理并且变得越来越不相关

于 2013-09-10T08:24:00.427 回答
2

要将元素打印到单元格,请替换:

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 的语法错误

于 2013-11-14T19:23:46.243 回答
2

CSS 选择器:

您还可以使用CSS 选择#images img[src^='img/']

这表示具有 id 的元素images包含标记名img,其属性src的值以 开头'img/'

#用于 id ;[]对于属性;^for 开头;#images img,imgimages.


CSS查询:

CSS 查询


由于将匹配多个元素,您将使用 的.querySelectorAll方法,document然后循环返回的长度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
于 2018-06-26T08:30:13.967 回答