首页 > 解决方案 > 我正在尝试使用 Excel VBA 抓取网站数据

问题描述

所以我首先要说我对 VBA 很陌生。我正在尝试从此页面上的表中提取数据。就代码而言,我还没有完成太多,所以请放轻松。我正在寻找一些关于如何处理它以及是否可以完成的方向,我相信它可以。如果有人能够帮助指导我朝着正确的方向前进,那将不胜感激。

Sub rgnbateamstats()

Dim appIE As Object
Set appIE = CreateObject("internetexplorer.application")


With appIE
.navigate "https://rotogrinders.com/team-stats/nba-earned?site=draftkings"
.Visible = True
End With

Do While appIE.Busy
DoEvents
Loop

Set allRowOfData = appIE.document.getElementById("proj-stats")

不确定从这里去哪里,或者我是否走在正确的轨道上。

标签: excelvbaweb-scraping

解决方案


这将抓取该页面上的整个表格。

本项目使用早期绑定。您需要将引用设置为:

  • 微软互联网控制
  • Microsoft HTML 对象库

您可以在 VBE > 工具 > 参考中完成此操作。

我会说,这个网站在设置他们的表格时使用了一种非常奇怪的方法,找到一种体面的方法来完成这一点很有趣。

此外,您可能会或可能不会接受的另一件事是,此表中有隐藏的列不会显示在网站上,但会显示在您的 Excel 文档中。如果您对此不满意,您可以在执行此代码后简单地删除或隐藏它们 - 或者如果您要修改它以防止在执行期间发生这种情况,那么您将获得更多权力。

Option Explicit

Sub rgnbateamstats()

    Const url$ = "https://rotogrinders.com/team-stats/nba-earned?site=draftkings"

    Dim IE As New InternetExplorer, doc As HTMLDocument
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets(1)
    
    With IE
        .Navigate url
        .Visible = True
        ieBusy IE
        Set doc = .Document
    End With
    
    Dim r As Long, c As Long, tCol As HTMLDivELement
    Dim subTbls(): subTbls = Array("rgt-bdy left", "rgt-bdy mid", "rgt-bdy right")
    
    Dim subTbl As Long        
    For subTbl = 0 To 2
        For Each tCol In getSubTblCols(doc, subTbls(subTbl)).getElementsByClassName("rgt-col")
            c = c + 1
            For r = 1 To tCol.getElementsByTagName("div").Length
                ws.Cells(r, c) = tCol.getElementsByTagName("div")(r - 1).innerText
            Next
        Next tCol
    Next subTbl

End Sub
Private Function getSubTblCols(doc As HTMLDocument, ByVal className$) As HTMLDivElement
    Dim tbl As HTMLTable
    Set tbl = doc.getElementById("proj-stats")
    Set getSubTblCols = tbl.getElementsByClassName(className)(0).Children(0). _
            Children(1)
End Function
Private Sub ieBusy(ieObj As InternetExplorer)
    With ieObj
        Do While .Busy Or .ReadyState < READYSTATE_COMPLETE
            DoEvents
        Loop
    End With
End Sub

好的,是时候尝试这里发生的事情了。

您的表中有三个子表。这是解释它的最佳方式,但这意味着您将首先使用以下行遍历每个子表:

For subTbl = 0 To 2

在该循环中,您将使用以下行循环该子表的列:

For Each tCol In getSubTblCols(doc, subTbls(subTbl)).getElementsByClassName("rgt-col")

rgt-col是每个表中列的类名 - 所以至少那部分很容易。该函数getSubTblCols抓取数组中子表的三个名称之一的主子表元素类名subTbls()

c是您的 Excel 列号,r是行号。您还可以使用rHTML 的每个行号,但它是 uses base 0,因此您必须减去 1。

然后使用单元格的innerText属性获取单元格的值,将其放入电子表格中,然后冲洗并重复。

我将您繁忙的网页功能移至新的子目录,ieBusy. 我还添加了该.readyState属性,因为正如我在评论中所说.busy,它本身充其量是不可靠的。


推荐阅读