首页 > 解决方案 > XML 响应未返回页面的完整 HTML

问题描述

我正在尝试将网球运动员的统计数据从该网站抓取到一个 excel 文档中以便于查看:http ://www.tennisabstract.com/cgi-bin/player.cgi?p=DominicThiem (示例球员)。

我以前用 VBA 做过几次刮擦,所以我对刮擦并不是完全陌生,但我知道这个问题更有可能是由于我缺乏知识而不是我正在使用的应用程序的固有问题!当我debug.print上面网页的内部 HTML 时,HTML 与我检查页面上的元素时不同。这是抓取返回的完整 HTML,显然不完整:

<TABLE width=1280>
<TBODY>
<TR>
<TD align=left>This site is slow and ugly in Internet Explorer. In <A href="https://www.google.com/intl/en/chrome/browser/">Chrome</A> or <A href="http://www.mozilla.org/en-US/firefox/new/">Firefox</A>, it is much faster and a bit less ugly.<BR>&nbsp;</TD>
<TD align=right><A href="http://www.tennisabstract.com/blog">HeavyTopspin.com</A> | <A href="https://twitter.com/#!/tennisabstract">Twitter</A> </TD></TR></TBODY></TABLE>
<DIV id=header>
<TABLE width=1240>
<TBODY>
<TR>
<TD class=headline align=left>
<H1><SPAN class=blackheader><A href="http://www.tennisabstract.com/">tennis<SPAN style="COLOR: blue">abstract</SPAN>.com</SPAN></H1></A></TD>
<TD id=playersearch style="VERTICAL-ALIGN: top" align=right>&nbsp;</TD></TR>
<TR>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD></TR>
<TR>
<TD style="VERTICAL-ALIGN: top" align=left><SPAN id=bio>&nbsp;</SPAN> <SPAN id=tabResults class=tabview style="BACKGROUND-COLOR: #e6eeee">&nbsp;<B>Singles Results</B>&nbsp;</SPAN>&nbsp; <SPAN id=tabHead class="tablink tabview" style="BACKGROUND-COLOR: #e6eeee">&nbsp;<B>Head-to-Heads</B>&nbsp;</SPAN>&nbsp; <SPAN id=tabEvents class="tablink tabview" style="BACKGROUND-COLOR: #e6eeee">&nbsp;<B>Event Records</B>&nbsp;</SPAN> <BR><SPAN id=tabDubs class="tablink tabview" style="POSITION: relative; TOP: 5px; BACKGROUND-COLOR: #e6eeee">&nbsp;<B>Doubles Results</B>&nbsp;</SPAN><SPAN id=tabDubsSpacer>&nbsp;&nbsp;</SPAN> <SPAN id=shotsHere></SPAN></TD>
<TD id=wonloss style="VERTICAL-ALIGN: top" align=right>&nbsp;</TD></TR>
<TR>
<TD id=tabmenu style="VERTICAL-ALIGN: top" align=left>&nbsp; </TD>
<TD>&nbsp;</TD></TR>
<TR>
<TD id=playernews colSpan=2>&nbsp;</TD></TR></TR></TBODY></TABLE></DIV>
<DIV id=main>
<TABLE id=maintable width=1280>
<TBODY>
<TR id=tabletoggles>
<TD>&nbsp;</TD>
<TD id=tablelabel>&nbsp;</TD>
<TD id=abovestats class=abovestats align=right>&nbsp;&nbsp;&nbsp;<SPAN class="revscore likelink"></SPAN> &nbsp;&nbsp;&nbsp;<B>Stats:</B>&nbsp; <SPAN class="statsa stattab">Overview</SPAN><SPAN class=statspacer>&nbsp;|&nbsp;</SPAN><SPAN class="statso stattab">Serve</SPAN>&nbsp;|&nbsp;<SPAN class="statsr stattab likelink">Return</SPAN>&nbsp;|&nbsp;<SPAN class="statsw stattab likelink">Raw</SPAN> </TD></TR>
<TR>
<TD id=footer class=footer>&nbsp;</TD>
<TD id=stats class=stats colSpan=2>
<TABLE id=matches>
<TBODY></TBODY></TABLE></TD></TR>
<TR>
<TD id=belowmenus>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;</TD>
<TD id=belowmatches colSpan=2>&nbsp;</TD></TR></TBODY></TABLE></DIV>
<DIV></DIV>

我正在尝试抓取页面下半部分的“主”表,该表显示了玩家最近的比赛(id =“matches”,从上述 HTML 底部开始的第 6 行)。当我检查网页本身的元素时,表格看起来应该很容易抓取,但我的抓取没有返回完整的 HTML,因此我无法在代码中引用任何内容。

我认为这可能是由于我的 XML 没有完全加载,所以尝试了这个,它返回相同的 HTML。

这是我到目前为止使用的代码:

Sub TennisStats()

    Dim XMLPage As New MSXML2.XMLHTTP60
    Dim HTMLDoc As New MSHTML.HTMLDocument

    Application.ScreenUpdating = False

    player1 = ThisWorkbook.Worksheets(1).Range("B1").Value
    player1 = Replace(player1, " ", "")

    With XMLPage
        .Open "GET", "http://www.tennisabstract.com/cgi-bin/player.cgi?p=" & player1
        .send

        HTMLDoc.body.innerHTML = .responseText

    End With

    Debug.Print HTMLDoc.body.innerHTML

End Sub

标签: htmlvbaexcel

解决方案


您不能使用 XMLHTTP,因为没有时间加载数据。

此外,它似乎不想通过 Internet 控制使用 IE 为我工作,所以我使用 selenium basic 切换到 Chrome。如果您安装selenium basic,您还需要转到 VBE > 工具 > 参考 > 添加对 Selenium 类型库的引用。Selenium 支持多种浏览器,包括 FireFox、Chrome、IE 和 Opera。

如果使用 Chrome,请确保您拥有最新的 Chrome 安装和最新的ChromeDriver 安装,并且 ChromeDriver.exe 位于环境路径上的文件夹中,除非您希望将可执行文件的路径作为参数传递给 selenium。

Option Explicit
Public Sub GetTable()
    Dim d As WebDriver, html As HTMLDocument, hTable As HTMLTable
    Set d = New ChromeDriver: Set html = New HTMLDocument
    Const URL = "http://www.tennisabstract.com/cgi-bin/player.cgi?p=DominicThiem"

    With d
        .Start "Chrome"
        .get URL
        html.body.innerHTML = .PageSource
        Set hTable = html.getElementById("matches")
        WriteTable hTable, 1, ThisWorkbook.Worksheets("Sheet1")
        .Quit
    End With
End Sub
Public Sub WriteTable(ByVal hTable As HTMLTable, Optional ByVal startRow As Long = 1, Optional ByVal ws As Worksheet)
    If ws Is Nothing Then Set ws = ActiveSheet
    Dim tRow As Object, tCell As Object, tr As Object, td As Object, r As Long, c As Long
    r = startRow
    With ws
        Dim headers As Object, header As Object, columnCounter As Long
        Set headers = hTable.getElementsByTagName("th")
        For Each header In headers
            columnCounter = columnCounter + 1
            .Cells(startRow + 1, columnCounter) = header.innerText
        Next header
        Set tRow = hTable.getElementsByTagName("tr")
        For Each tr In tRow
            r = r + 1
            Set tCell = tr.getElementsByTagName("td")
            c = 1
            For Each td In tCell
                Select Case c
                Case 16
                    .Cells(r, c).Value = "'" & td.innerText
                Case Else
                    .Cells(r, c).Value = td.innerText
                End Select
                c = c + 1
            Next td
        Next tr
    End With
End Sub

示例网页视图:

在此处输入图像描述


样本硒输出:


推荐阅读