【问题标题】:Failproof Wait for IE to loadFailproof 等待 IE 加载
【发布时间】:2014-04-25 17:06:18
【问题描述】:

有没有万无一失的方法让脚本等到 Internet Explorer 完全加载?

oIE.Busy 和/或oIE.ReadyState 都没有按应有的方式工作:

Set oIE = CreateObject("InternetExplorer.application")

    oIE.Visible = True
    oIE.navigate ("http://technopedia.com")

    Do While oIE.Busy Or oIE.ReadyState <> 4: WScript.Sleep 100: Loop  

    ' <<<<< OR >>>>>>

    Do While oIE.ReadyState <> 4: WScript.Sleep 100: Loop

还有其他建议吗?

【问题讨论】:

  • 请描述您展示的传统Do ... Loop 有什么问题?
  • 看起来它在继续其他操作之前没有等待足够的页面加载,从而给出“需要元素错误”。当我明确增加等待时间时,效果很好。
  • 我曾经发现过类似的行为,解决方案只是在此之前添加额外的循环,例如Do While oIE.ReadyState = 4: WScript.Sleep 100: Loop。所以第一步是等到“导航开始”,第二步 - 直到它完成。
  • 我不确定你的建议是什么。你能详细说明一下吗?
  • @user3408723 不敢相信我在评论 2014 年的事情......但我遇到了同样的问题,欧米茄的回答实际上是有道理的。主循环之前的代码行位于 event 中,即代码在 IE 实际处理请求之前命中您的循环 - 因此,在它变为 Busy 之前。代码运行得太快,并且在 IE 有机会变得忙碌之前就进入了循环,因此它绕过了循环,因为它在技术上并不忙。非常聪明地研究答案,我从来没有考虑过。

标签: internet-explorer web-scraping vbscript wsh readystate


【解决方案1】:

试试这个,它帮助我用IE解决了一次类似的问题:

Set oIE = CreateObject("InternetExplorer.application")
oIE.Visible = True
oIE.navigate ("http://technopedia.com")
Do While oIE.ReadyState = 4: WScript.Sleep 100: Loop
Do While oIE.ReadyState <> 4: WScript.Sleep 100: Loop
' example ref to DOM
MsgBox oIE.Document.GetElementsByTagName("div").Length

UPD: 深入IE 事件我发现IE_DocumentComplete 是页面实际准备好之前的最后一个事件。因此,还有另一种方法可以检测网页何时加载(请注意,您必须指定可能与目标 URL 不同的确切目标 URL,例如在重定向的情况下):

option explicit
dim ie, targurl, desturl, completed

set ie = wscript.createobject("internetexplorer.application", "ie_")
ie.visible = true

targurl = "http://technopedia.com/"
desturl = "http://technopedia.com/"

' targurl = "http://tumblr.com/"
' desturl = "https://www.tumblr.com/" ' redirection if you are not login
' desturl = "https://www.tumblr.com/dashboard" ' redirection if you are login

completed = false
ie.navigate targurl
do until completed
    wscript.sleep 100
loop
' your code here
msgbox ie.document.getelementsbytagname("*").length
ie.quit

sub ie_documentcomplete(byval pdisp, byval url)
    if url = desturl then completed = true
end sub

【讨论】:

【解决方案2】:

我已经成功使用了很长时间:

While IE.readyState <> 4 Or IE.Busy: DoEvents: Wend

它一直运行良好,直到今天,当我更换我的 PC 并切换到 Windows 10 和 Office 16 时。然后它开始在某些情况下工作,但有时循环没有完成。循环中的任何一个条件都没有达到,所以循环是 ENDLESS。

经过大量谷歌搜索,我尝试了很多建议,直到我在这篇文章中找到了解决方案:Excel VBA Controlling IE local intranet

解决方案是将 URL 添加到 Internet Explorer 安全选项卡中的受信任站点列表中。终于!

【讨论】:

    【解决方案3】:

    几年后,它也击中了我。我查看了建议的解决方案并进行了很多测试。已经开发了以下命令组合,我现在将在我的应用程序中使用它们。

    Set oIE = CreateObject("InternetExplorer.application")
    
    oIE.Visible = True
    oIE.navigate ("http://technopedia.com")
    
    wscript.sleep 100
    Do While oIE.Busy or oIE.ReadyState <> 4: WScript.Sleep 100: Loop  
    
    wscript.sleep 100
    Do While oIE.Busy or oIE.ReadyState <> 4: WScript.Sleep 100: Loop  
    
    msgbox oIE.ReadyState & " / " & oIE.Busy , vbInformation +  vbMsgBoxForeground , "Information"
    
    oIE.Quit
    
    set oIE = Nothing
    

    在发现 oIE.Busy = True 有时在第一个循环之后,我确实安装了第二个相同的循环。

    问候, 脚本人

    【讨论】:

      【解决方案4】:

      试着把这个脚本放在最上面,这样可以解决你的问题。

      { 
          $myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
          $myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID);
          $adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;
      
          if ($myWindowsPrincipal.IsInRole($adminRole)) {
              $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)";
              Clear-Host;
          }
          else {
              $newProcess = New-Object System.Diagnostics.ProcessStartInfo "PowerShell";
              $newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"
              $newProcess.Verb = "runas";
              [System.Diagnostics.Process]::Start($newProcess);
              Exit;
          }
      }
      

      解释:

      当您从正常模式运行脚本时,Powershell 没有某些权限 所以它没有正确读取 IE 状态 这就是为什么没有加载 DOM 所以,脚本没有找到任何参数

      【讨论】:

        【解决方案5】:

        所以通过查找这个答案,我仍然遇到了 IE 等待页面完全加载的问题。希望此解决方案对其他人有所帮助,这就是我所做的:

        Dim i As Integer
        Dim j As Integer
        Dim tagnames As Integer
        
        While ie.Busy
            DoEvents
        Wend
        While ie.ReadyState <> 4
            DoEvents
        Wend
        
        i = 0
        j = 0
        While (i <> 5)
            i = 0
            tagnames = ie.document.getelementsbytagname("*").Length
            For j = 1 To 5
                Sleep (50)
                If tagnames = ie.document.getelementsbytagname("*").Length Then
                    b = b + 1
                End If
            Next j
        Wend
        

        基本上,它的作用是等待 5 个 50 毫秒的间隔,以使加载的标记名数量停止增加。 当然,这可以根据您的需要进行调整,但这适用于我的应用程序。

        【讨论】:

          【解决方案6】:

          如果您使用 IE 处理表单提交,最好将其放在 Sub 中,这样您就可以重复引用同一个 Sub。

          Dim IE
          Set IE = WScript.CreateObject("InternetExplorer.Application")
              IE.Visible = True
              IE.Navigate "http://www.google.com"
              Wait IE, 500
          
          Sub Wait(IE, SleepInterval)
              Do
                  WScript.Sleep SleepInterval
              Loop While IE.ReadyState < 4 Or IE.Busy
          End Sub
          

          不同之处在于,您在 wscript.sleep 之后引用了 IE 对象。如果您在加载对象之前首先检查它们。它可能导致脚本失败。

          【讨论】:

          • 应该是Loop While IE.ReadyState &lt; 4 Or IE.Busy
          • 已更新。谢谢欧米茄。
          • 第 2 行末尾缺少右括号。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-11-16
          • 1970-01-01
          • 2016-07-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多