我可以为其他网站回收网页搭建Excel VBA脚本吗?

问题描述 投票:-1回答:1

所以在我之前的帖子中,Here,每个人都有这么大的帮助,但不幸的是我没有从中学到很多东西。是否有可能回收其中一个脚本来刮掉this page并将已确认/预计的阵容拉入Excel?看到html后,我看到它们被安置在“lineups is-compact”div类中,然后在“lineup is-nba”div类中分开。

我正在尝试获得球队名称,球员姓名和预期/确认。

以下是提供相同信息的其他网站,它们更容易从中获取。

RotoGrinders <其他代码为BB Monster创建的地方相同

这是我最终使用的代码,因为修改其他任务似乎更简单。男孩,我错了。

Option Explicit 
Public Sub GetInfo()

Dim IE As New InternetExplorer, iColumns As Object, iRow As Object, i As Long, j As Long, r As Long, c As Long

Application.ScreenUpdating = False

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

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

    Set iColumns = .document.querySelectorAll(".rgt-col")

    With ThisWorkbook.Worksheets("Sheet1")
        For i = 0 To iColumns.Length - 1
            c = c + 1: r = 0
            Set iRow = iColumns.item(i).getElementsByTagName("div")
            For j = 0 To iRow.Length - 1
                r = r + 1
                .Cells(r, c) = iRow(j).innerText
            Next
        Next
    End With
    Application.ScreenUpdating = True
    .Quit
End With
End Sub

请记住,我有4天的经验。各方面都是Noob。

excel vba excel-vba web-scraping
1个回答
2
投票

关于网页抓取的一个令人愉快且具有挑战性的事情是,通常每个网站都是不同的,并且通常属于同一网站的网页可能不同。我认识到你只有一点经验,所以我担心以下是一个学习曲线。您的其他答案的脚本非常基本,在表格格式的列中循环,然后是行。

所有这一切的可转移部分是学习如何阅读HTML,决定何时使用XMLHTTP(我在下面使用它并且是一种更快的检索方法但不会检索页面上的所有内容 - 特别是如果页面是javascript重)与浏览器相比基于解决方案练习使用检查/开发工具来选择信息。

然后,每次都会使用常见的代码,例如,使用IE时,您几乎总会拥有相同的代码连接行并等待代码行。使用xmlHttp,您通常也会重复使用开放的代码行。但是,因为网站通常是非常不同的,你需要探索如何每次解析DOM以获得你想要的信息。对于属于同一站点/主机的页面,如果开发人员的页面设计一致,则可以重用更多代码。只是不要指望这种情况。

下面的脚本使用querySelectorAll,在本例中是HTMLDocument的方法,最初通过匹配nodeLists上的元素生成class names

下面的这些行产生了您可能认为的列表。列表中的每个元素都具有相同的类名。

Set teamsVisitors = .querySelectorAll(".lineup__team.is-visit")
Set teamsHomies = .querySelectorAll(".lineup__team.is-home")
Set nickNamesVisitors = .querySelectorAll(".lineup__mteam.is-visit")
Set nickNamesHomies = .querySelectorAll(".lineup__mteam.is-home")
Set visitors = .querySelectorAll(".lineup__list.is-visit") '  then by li
Set homies = .querySelectorAll(".lineup__list.is-home") ' then by li

那么,让我们来看看其中一个列表。与之相关的nodeList

Set teamsVisitors = .querySelectorAll(".lineup__team.is-visit")

你可以看到这是如何将4个访客团队的2个字母名称聚集到nodeList(你可以认为集合,但你不能For Each超过它,它实际上更像是一个数组)。

我已经给出了变量相当具有描述性的名称,因此您可以了解每个列表中的内容,但如果不确定,您可以进入开发人员工具(Chrome中的F12,FireFox),在元素选项卡中突出显示任何HTML,然后按Ctrl键+ F打开搜索HTML框并在""中输入querySelectorAll之间的文本到该框中,例如.lineup__team.is-visit

您可以看到它返回CSS选择器的HTML中的匹配数。您可以使用enter来循环它们。

所以,我有一系列的nodeLists。每个索引,例如指数0,在每个nodeList,与同一场比赛有关。所以,在索引0我有GS v BKN i.e. Warriors v Nets

我将nodeLists循环写入匹配信息。为了获得确认/玩家信息,我需要进一步细分我所拥有的nodeLists:

Set visitors = .querySelectorAll(".lineup__list.is-visit") '  then by li
Set homies = .querySelectorAll(".lineup__list.is-home") ' then by li

0取指数visitors nodeList我们有:

我们需要进一步拆分这些信息;仅使用类名是不够的。如果我们看一下HTML,我们可以看到实际上,单个项目被分成li list标签元素:

这意味着我们可以使用.getElementsByTagName方法返回这些项目。例如:

homies.item(i).getElementsByTagName("li")

然后最终看起来像这样(样本):

在我的循环中,我将访问者写到左栏,并在右侧居住。当我遍历原始nodeLists中的索引(即每个匹配)时,我将+3添加到输出列编号,以便您获得每个表的间隔写入。


示例输出:

enter image description here


VBA:

Option Explicit
Public Sub GetMatchInfo()
    Dim sResponse As String, html As HTMLDocument
    Application.ScreenUpdating = False

    With CreateObject("MSXML2.XMLHTTP")
        .Open "GET", "https://www.rotowire.com/basketball/nba-lineups.php", False
        .setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
        .send
        sResponse = StrConv(.responseBody, vbUnicode)
    End With

    Set html = New HTMLDocument

    Dim visitors As Object, teamsVisitors As Object, nickNamesVisitors As Object
    Dim homies As Object, teamsHomies As Object, nickNamesHomies As Object
    Dim i As Long, r As Long, c As Long, j As Long

    With html
        .body.innerHTML = sResponse
        Set teamsVisitors = .querySelectorAll(".lineup__team.is-visit")
        Set teamsHomies = .querySelectorAll(".lineup__team.is-home")
        Set nickNamesVisitors = .querySelectorAll(".lineup__mteam.is-visit")
        Set nickNamesHomies = .querySelectorAll(".lineup__mteam.is-home")
        Set visitors = .querySelectorAll(".lineup__list.is-visit") '  then by li
        Set homies = .querySelectorAll(".lineup__list.is-home") ' then by li
    End With

    With ThisWorkbook.Worksheets("Sheet1")
        r = 1: c = 1

        For i = 0 To teamsHomies.Length - 1
            .Cells(r, c) = teamsVisitors.item(i).innerText
            .Cells(r, c + 1) = teamsHomies.item(i).innerText

            r = r + 1
            .Cells(r, c) = nickNamesVisitors.item(i).innerText
            .Cells(r, c + 1) = nickNamesHomies.item(i).innerText

            Dim numHomiesLiElements As Long, numVisitorsLiElements As Long, maxNumberofLiElements As Long

            numHomiesLiElements = homies.item(i).getElementsByTagName("li").Length - 1
            numVisitorsLiElements = visitors.item(i).getElementsByTagName("li").Length - 1

            maxNumberofLiElements = IIf(numHomiesLiElements > numVisitorsLiElements, numHomiesLiElements, numVisitorsLiElements)
            For j = 0 To maxNumberofLiElements
                r = r + 1
                On Error Resume Next
                .Cells(r, c) = visitors.item(i).getElementsByTagName("li")(j).innerText
                .Cells(r, c + 1) = homies.item(i).getElementsByTagName("li")(j).innerText
                On Error GoTo 0
            Next

            r = 1: c = c + 3
        Next

    End With

    Application.ScreenUpdating = True

End Sub

参考文献(VBE>工具>参考文献):

  1. Microsoft HTML对象库

资源可以帮助您:

  1. getElementsByTagName
  2. CSS Class selectors
  3. XMLHTTP requests

请参阅此处以获得改进的基于Python的脚本:

https://stackoverflow.com/a/55626217/6241235

© www.soinside.com 2019 - 2024. All rights reserved.