为什么我的Excel VBA宏仅可用于两个类似的网站之一来查找高尔夫球手的残障并捕获结果?

时间:2018-07-30 21:54:03

标签: excel vba internet-explorer iframe web-scraping

我认为问题与iframe有关。我让Selenium记录并在两个站点上运行该过程。我在生成的Selenium代码中看到的唯一区别是,在GHIN站点上,Selenium运行一个Command:“选择框架” Target:“ index = 0”。我相信这会到达iframe(0)框架,但我还没有 找到了VBA代码以渗透对我需要的元素ID的访问。稍后再详细介绍。不太可能的是,必须以不同的方式处理GHIN网站上对AJAX的使用吗?在检查HTML方面,iframe和AJAX对我而言是最明显的区别。这两个站点似乎都使用JSCRIPT,表格和表单。

我在Excel电子表格中查找并捕获了Golf Handicap更新,以获取大约50个高尔夫球手的列表。修订后的差点每月发出两次。我的高尔夫球手分为两个障碍服务站点:

https://www.golfhandicapnetwork.com/DefaultLookup.aspx(Handicomp) http://www.ghin.com/lookup.aspx(GHIN)

我编写了一个Excel宏,可以完成Handicomp的工作,但是无法在GHIN网站上使用相同的方法。这是GHIN的VBA宏,使用了我尝试访问iframe元素(建议错误424对象)的建议方法。我用注释对代码进行注释,以显示非常相似的Handicomp障碍服务查询网站的替换代码。我排除了从电子表格中获取查找条件的代码,提取了查找结果,然后将其输入电子表格中,以最大程度地减少代码,并集中精力于无法在iframe中的GHIN网站上获取getElementById。我列出了有关我的失败调整的更多详细信息,以便在CODE之后访问iframe元素。该子查询仅查找亚利桑那州的一个常用名(Smith)。我还将InternetExplorer保持打开状态以查看查找结果。

Sub HCLookupGHIN()
  Dim objIE As InternetExplorer 
  Dim doc As HTMLDocument
  Set objIE = CreateObject("InternetExplorer.application")
With objIE
  .Visible = True
         .navigate "http://www.ghin.com/lookup.aspx" '1
  'Wait for loading
Do While objIE.Busy Or objIE.readyState <> 4: DoEvents: Loop
End With
Set doc = objIE.document
' for GHIN need to click the Name & State lookup tab 
        doc.frames(0).document.getElementById("__tab_ctl00_bodyMP_tcLookupModes_tpNameState").Click  '2 Err 424 Object Required (Also Run-time error Access is denied)
' Find and Select State from Drop Down List
        doc.frames(0).document.getElementById("ctl00_CPH0_ddlState").Click  '3
        Set oState = doc.frames(0).document.getElementById("ctl00_bodyMP_tcLookupModes_tpNameState_cboState")  '4
  For i = 1 To oState.Options.Length
    If oState.Options(i).Text = State Then
      oState.selectedIndex = i
      Exit For
    End If
  Next i
        doc.frames(0).document.getElementById("ctl00_bodyMP_tcLookupModes_tpNameState_tbLastName").Value = LastN  '5
        doc.frames(0).document.getElementById("ctl00_bodyMP_tcLookupModes_tpNameState_tbFirstName").Value = FirstN  '6
        doc.frames(0).document.getElementById("ctl00_bodyMP_tcLookupModes_tpNameState_btnSubmit2").Click  '7

'Replacement code for Handicomp Sub. This code works for me. Replace annotated statements '1-'7 
'1  .navigate "https://www.golfhandicapnetwork.com/DefaultLookup.aspx"
'2    no code required for Handicomp. Name & State input available 
'3  doc.getElementById("ctl00_CPH0_ddlState").Click
'4  Set oState = doc.getElementById("ctl00_CPH0_ddlState") 
'5  doc.getElementById("ctl00_CPH0_lastNameLookupTxtBox").Value = LastN
'6  doc.getElementById("ctl00_CPH0_firstNameLookupTxtBox").Value = FirstN
'7  doc.getElementById("ctl00_CPH0_submit_lookup_nam_btn").Click 'Click submit button

End Sub

我无法使用以下命令在默认的GHIN Single Player查找中输入数据:

doc.getElementById(“ ctl00_bodyMP_tcLookupModes_tpSingle_tbGHIN”)。Value =“ 0000”(或其他frame(0)和iframe ID构造)

因此,我得出的结论是,我只是没有找到访问iframe的秘密通道。单击“名称和状态”查找选项卡不仅仅是一个问题。

我也无法使用以下方法获取GHIN名称和状态查找表(这是我真正需要的): doc.getElementById(“ __ tab_ctl00_bodyMP_tcLookupModes_tpNameState”)。点击

我还尝试使用以下VBA代码在iframe(0)(语句“ 2”)中获取ElementById:

doc.getElementById(ghinwidget_iFrame_0).contentDocument.getElementById(“ __ tab_ctl00_bodyMP_tcLookupModes_tpNameState”)。单击[运行时错误91对象变量或未设置块的情况]

doc.getElementById(ghinwidget_iFrame_0).document.getElementById(__ tab_ctl00_bodyMP_tcLookupModes_tpNameState)。单击[运行时错误91对象变量或未设置块]

尝试了其他一些类似的构造都没有用。我花了很多时间寻找答案。对不起,如果我错过了。

这两个网站看起来非常相似。帮助解决我的无知。我是互联网自动化和VBA编程的初学者,但是我认为我即将自动化此障碍查询任务并将结果放入电子表格中。一堆老高尔夫球手(特别是我)将对您的帮助大加赞赏。希望您有一个简单的答案或可以建议另一种方法。

1 个答案:

答案 0 :(得分:0)

权限被拒绝,same origin policy

您的问题是由于src的{​​{1}}链接不同,其中包含您要单击的选项卡。因此,尝试单击时您将获得拒绝访问的权限;我认为是出于相同的原产地政策。

使用IE,您可以通过直接导航到该iframe链接来解决此问题。使用硒(我也向您展示了如何解决),您可以将帧切换为访问。另外,这可能对IE尤其重要。


目标src需要新文档

required src


Internet Explorer:

src

需要参考:

VBE>工具>参考>

  1. Microsoft Internet控件
  2. HTML对象库

基本硒:

您在这里和selenium basic一起去。安装后,通过工具>引用将引用添加到硒类型库。

Public Sub GetInfo2()
    Dim ie As New InternetExplorer, html As New HTMLDocument, state As String, surname As String
    state = "AZ": surname = "Smith"
    Application.ScreenUpdating = False
    With ie
        .Visible = True
        .navigate "http://162.245.224.193/Widgets/HandicapLookupEntry.aspx?widget=HandicapLookupEntry&small=0&css=default&showheader=1&showheadertext=1&showfootertext=1&TestDB=0"

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

        With .document
            .getElementById("__tab_ctl00_bodyMP_tcLookupModes_tpNameState").Click
            .querySelector("option[value=" & state & "]").Selected = True
            .getElementById("ctl00_bodyMP_tcLookupModes_tpNameState_tbLastName").innerText = surname
            .getElementById("ctl00_bodyMP_tcLookupModes_tpNameState_btnSubmit2").Click
        End With

        While .Busy Or .readyState < 4: DoEvents: Wend
        Dim flagElement As Object
        Do: DoEvents: On Error Resume Next: Set flagElement = .document.getElementById("ctl00_bodyMP_lnkGoBack"): On Error GoTo 0: Loop While flagElement Is Nothing

        Dim hTable As HTMLTable, iRow As htmltablerow, iCell As HTMLTableCell, r As Long, c As Long
        Set hTable = .document.getElementsByTagName("form")(0).getElementsByTagName("table")(1)

        With Worksheets("Sheet1")
            For Each iRow In hTable.getElementsByTagName("tr")
                r = r + 1: c = 0
                For Each iCell In iRow.getElementsByTagName("td")
                    c = c + 1
                    .Cells(r, c) = iCell.innerText
                Next
            Next
        End With
    End With
    Application.ScreenUpdating = True
End Sub

对于您的其他网站:

Option Explicit
Public Sub GetInfo()
    Dim d As WebDriver
    Set d = New ChromeDriver
    Const url = "http://www.ghin.com/lookup.aspx"
    Application.ScreenUpdating = False
    With d
         '.AddArgument ("--no-sandbox")           '<== Uncomment me if dev extension error
         '.AddArgument ("--disable-extensions") '<== Uncomment me if dev extension error
        .AddArgument "--headless".AddArgument "--headless"
        .Start "Chrome"
        .get url
        .SwitchToFrame .FindElementByTag("iframe", timeout:=7000)
        .FindElementById("__tab_ctl00_bodyMP_tcLookupModes_tpNameState").Click
        .FindElementById("ctl00_bodyMP_tcLookupModes_tpNameState_cboState").AsSelect.SelectByText "Arizona"
        .FindElementById("ctl00_bodyMP_tcLookupModes_tpNameState_tbLastName").SendKeys "Smith"
        .FindElementById("ctl00_bodyMP_tcLookupModes_tpNameState_btnSubmit2").Click
        Dim e As Object
        Set e = .FindElementById("ctl00_bodyMP_lnkGoBack", timeout:=10000)
        Dim a As Object, iRow As Object, iCell As Object, r As Long, c As Long
        Set a = .FindElementByTag("form").FindElementsByTag("table")(2)
        With Worksheets("Sheet1")
            For Each iRow In a.FindElementsByTag("tr")
                r = r + 1: c = 0
                For Each iCell In iRow.FindElementsByTag("td")
                    c = c + 1
                    .Cells(R, c) = iCell.Text
                Next
            Next
        End With
        .Quit
        Application.ScreenUpdating = True
    End With
End Sub

参考:

VBE>工具>参考:

  1. Microsoft Forms 2.0对象库(如果将Form对象添加到项目中,则会自动添加)
  2. 硒类型库