onchange 和 onclick 不能始终如一地工作

onchange and onclick not work consistantly

我正在尝试从网页中抓取数据。在这个过程中,我需要改变其中一个 该网页的下拉列表。我能够做到这一点。但是当我手动更改 下拉菜单,网页会更改其内容,例如图像和其他一些文本。但是当我这样做的时候 使用 VBA 它不会那样做。我多次测试了我的代码。所以如果我 运行 程序 10 次它会更改内容 1 或 2 次。所以我对发生的事情感到困惑

这是那个下拉区域的HTML。

<tbody>
<tr>
<td class="label"><label for="pa_product">Product</label></td>
<td class="value"><select id="pa_product" name="attribute_pa_product" data-attribute_name="attribute_pa_product">
<option value="">Choose an option…</option>
<option value="air-xs-2-octo-16-inch" class="attached enabled">AIR XS 2 Octo 16 Inch</option>
<option value="air-xs-2-octo-18-inch" class="attached enabled">AIR XS 2 Octo 18 Inch</option>
<option value="air-xs-2-octo-20-inch" class="attached enabled">AIR XS 2 Octo 20 Inch</option>
</select> <a class="reset_variations" href="#reset">Clear selection</a></td>
</tr>
</tbody>

这是我开发的代码。我认为 onchange 和 onclick 很少起作用。

    Do
    DoEvents
    Loop Until objIE.readystate = 4

    'Body(HTML)
    'MsgBox objIE.document.getElementById("tab-description").outerHTML, , "OHTML"
    'MsgBox objIE.document.getElementById("tab-description").innerHTML, , "IHTML"
    'MsgBox objIE.document.getElementById("tab-description").innerText, , "ITex"
    WS.Range("D" & i).Value = objIE.document.getElementById("tab-description").outerHTML

    'Option 1 value
    'MsgBox objIE.document.getElementById("pa_product").outerHTML
    'MsgBox objIE.document.getElementById("pa_product").innerHTML
    'MsgBox objIE.document.getElementById("pa_product").innerText


    objIE.document.getElementById("pa_product").selectedindex = 1
    Application.Wait (Now + TimeValue("0:00:01"))
    'modify the web page for that selected item
    'For x = 1 To 5
    'objIE.document.getElementById("pa_product").selectedindex = 1
    Application.Wait (Now + TimeValue("0:00:03"))
    objIE.document.getElementById("pa_product").FireEvent ("onchange")
    objIE.document.getElementById("pa_product").FireEvent ("Onclick")
    objIE.document.getElementById("pa_product").FireEvent ("onmousedown")
    'Next x

    Application.Wait (Now + TimeValue("0:00:03"))

    WS.Range("J" & i).Value = objIE.document.getElementById("pa_product").Item(1).innerText

首先我使用了一个事件。但没有成功。所以我尝试使用我发现的所有事件。 FireAllEvents (objIE.document.getElementById("pa_product")) 函数 FireAllEvents(ByRef objHTML)

Function FireAllEvents(ByRef objHTML)
With objHTML
    .FireEvent ("onblur")
    .FireEvent ("onchange")
    .FireEvent ("oncontextmenu")
    .FireEvent ("onfocus")
    .FireEvent ("oninput")
    .FireEvent ("onreset")
    '.FireEvent ("onsearch")
    .FireEvent ("onkeydown")
    .FireEvent ("onkeypress")
    .FireEvent ("onkeyup")
    .FireEvent ("onclick")
End With
End Function

然后我这样调用这个函数

    FireAllEvents (objIE.document.getElementById("pa_product"))

    Application.Wait (Now + TimeValue("0:00:03"))

    WS_Oceanic.Range("J" & i).Value = objIE.document.getElementById("pa_product").Item(1).innerText
    objIE.document.getElementById("pa_product").Click   

但是也没用。
非常感谢你。

使用 VBA 的 selenium 基本包装器,这非常容易。安装后 selenium basic 您通过 VBE > 工具 > 参考添加对 Selenium 类型库的引用

Option Explicit
Public Sub MakeSelection()
    Dim d As WebDriver
    Set d = New ChromeDriver
    Const URL = "https://oceanicaus.com.au/products/oceanic-airxs-2-octopus/"

    With d
        .Start "Chrome"
        .get URL
        .FindElementById("pa_product").AsSelect.SelectByIndex 1   'You can also use  .SelectByText

        Stop
        .Quit
    End With
End Sub

有时您需要聚焦和取消聚焦某个元素,以便它接收一些事件,我发现是这样。下面的代码对我来说一直可靠地工作,尽管只进行了一些测试。

除了使用 selected 索引,您还可以使用选项的值来设置 select 值,这就是我在下面所做的。

Public Sub SOTest()
    Dim ie      As Object: Set ie = CreateObject("InternetExplorer.Application")
    Dim ele     As Object
    Const url   As String = "https://oceanicaus.com.au/products/oceanic-airxs-2-octopus"

    With ie
        .Navigate url
        .Visible = True

        Do Until .readystate = 4 And Not .busy
            DoEvents
        Loop

        Set ele = .document.getElementByID("pa_product")

        With ele
            .Focus
            .Value = "air-xs-2-octo-16-inch"
            .fireEvent ("onChange")
            .document.getElementsByTagName("button")(0).Focus
        End With

    End With
End Sub