html - 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> </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> </TD></TR>
<TR>
<TD> </TD>
<TD> </TD></TR>
<TR>
<TD style="VERTICAL-ALIGN: top" align=left><SPAN id=bio> </SPAN> <SPAN id=tabResults class=tabview style="BACKGROUND-COLOR: #e6eeee"> <B>Singles Results</B> </SPAN> <SPAN id=tabHead class="tablink tabview" style="BACKGROUND-COLOR: #e6eeee"> <B>Head-to-Heads</B> </SPAN> <SPAN id=tabEvents class="tablink tabview" style="BACKGROUND-COLOR: #e6eeee"> <B>Event Records</B> </SPAN> <BR><SPAN id=tabDubs class="tablink tabview" style="POSITION: relative; TOP: 5px; BACKGROUND-COLOR: #e6eeee"> <B>Doubles Results</B> </SPAN><SPAN id=tabDubsSpacer> </SPAN> <SPAN id=shotsHere></SPAN></TD>
<TD id=wonloss style="VERTICAL-ALIGN: top" align=right> </TD></TR>
<TR>
<TD id=tabmenu style="VERTICAL-ALIGN: top" align=left> </TD>
<TD> </TD></TR>
<TR>
<TD id=playernews colSpan=2> </TD></TR></TR></TBODY></TABLE></DIV>
<DIV id=main>
<TABLE id=maintable width=1280>
<TBODY>
<TR id=tabletoggles>
<TD> </TD>
<TD id=tablelabel> </TD>
<TD id=abovestats class=abovestats align=right> <SPAN class="revscore likelink"></SPAN> <B>Stats:</B> <SPAN class="statsa stattab">Overview</SPAN><SPAN class=statspacer> | </SPAN><SPAN class="statso stattab">Serve</SPAN> | <SPAN class="statsr stattab likelink">Return</SPAN> | <SPAN class="statsw stattab likelink">Raw</SPAN> </TD></TR>
<TR>
<TD id=footer class=footer> </TD>
<TD id=stats class=stats colSpan=2>
<TABLE id=matches>
<TBODY></TBODY></TABLE></TD></TR>
<TR>
<TD id=belowmenus> <BR> <BR> <BR> <BR> </TD>
<TD id=belowmatches colSpan=2> </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
解决方案
您不能使用 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
示例网页视图:
样本硒输出:
推荐阅读
- android - 如何从我的资产文件夹中访问 .docx 文件?
- r - 在 R 中使用绑定 tf_df
- python-3.x - 子类的父类中的参数使用什么类型提示?
- javascript - 直接评估 JavaScript AST
- java - 如果我只使用一次,我应该散列用户输入的密码吗?
- javascript - JavaScript 新手,需要将输入返回给函数的调用者。我做得对吗?
- javascript - 使用 react、redux、firestore 提交表单 - 未在 firestore 中创建集合
- html - 如何让我的展示图片位于导航栏后面
- javascript - 向状态添加数据
- asp.net-mvc - 如何避免 CSS 和捆绑地狱?