【问题标题】:onchange and onclick not work consistantlyonchange 和 onclick 无法始终如一地工作
【发布时间】:2018-11-02 08:17:53
【问题描述】:

我正在尝试从网页中抓取数据。在这个过程中,我需要改变一个 该网页的下拉菜单。我能够做到这一点。但是当我手动更改 下拉菜单,网页会更改其内容,例如图像和其他一些文本。但是当我这样做时 使用 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

onchange and onclick not work consistantly

首先我使用了一个事件。但没有成功。所以我尝试使用我发现的所有事件。 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   

但它也没有用。
非常感谢你。

【问题讨论】:

  • 有可以分享的网址吗?您是否还引入了足够长的等待内容更新的时间?事件之间有足够的时间吗?所有这些活动都需要吗?
  • 非常感谢您的回复。这是网页。 oceanicaus.com.au/products/oceanic-airxs-2-octopus
  • 你做了什么选择?您是否可以安装第 3 方开源软件,即 selenium basic?
  • 感谢您的回复。 selenium basic有官方网站吗?
  • 我的答案中包含了链接。

标签: javascript excel vba web scrape


【解决方案1】:

有时你需要聚焦和取消聚焦一个元素,以便它接收一些事件,或者我发现了。下面的代码对我来说一直很可靠,尽管只有几个测试。

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

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

【讨论】:

  • 非常感谢您的回复。我检查了程序。当我运行该程序时,它在第一次尝试时不起作用。但是,如果我再次运行它,它就会起作用。我想为几个 url 运行这个程序。所以我不能使用以下。因为它并不总是相同的。 .Value = "air-xs-2-octo-16-inch" 所以我用了这个。 .Value = CStr(Replace(ie.document.getElementByID("pa_product").Item(1).innerText, " ", "-")) 但它没有用。你能告诉我为什么你有 - 对于所有空间。谢谢。
  • 如果您愿意,您仍然可以使用选定的索引方法,只需确保聚焦/取消聚焦,这应该会起作用。不确定我是否理解您的第二个问题。正在设置 value 属性,而不是通过 Index 选择项目。您可以在页面的 html 中找到该值。您的问题是否更多关于将选项值映射到您的期望?
  • 我问你为什么使用air-xs-2-octo-16-inch 而不是AIR XS 2 Octo 16 Inch 我从你的回复中了解到air-xs-2-octo-16-inch 是html。而且我无法理解以下行的作用。它是否将焦点设置为“添加到购物车”按钮? .document.getElementsByTagName("button")(0).Focus非常感谢您的热心帮助。
  • 你可能需要为另一个元素提供焦点,我只是随机选择了一个。没有理由选择这个元素而不是另一个。
  • 非常感谢您的支持。
【解决方案2】:

使用用于 VBA 的 selenium 基本包装器非常容易。安装 selenium basic 后,您可以通过 VBE > Tools > References 添加对 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

【讨论】:

  • 非常感谢您的回答。而且我不知道我可以从 vba 控制 chrome。什么是“selenium basic”?它是类似于 imacro 的东西吗?有没有可以了解的网站?有官方网站吗?
  • Selenium basic 是 vba 的包装器。它允许您使用 selenium(自动化软件)像语法和功能一样自动化许多浏览器。在这种需要触发事件的场景中,它通常更有效。你可以在这里阅读更多信息:florentbr.github.io/SeleniumBasic 教程在这里:codingislove.com/browser-automation-in-excel-selenium
猜你喜欢
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 2018-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多