【问题标题】:scraping web vba tags nested抓取嵌套的 web vba 标签
【发布时间】:2018-08-07 17:00:44
【问题描述】:

如果我在链接中发现像这样嵌套的标签,我在使用 vba 进行网页抓取时总是会遇到问题

http://forebet.com

从左侧菜单中抓取链接数据,但是当我进入嵌套为英格兰,西班牙的锦标赛时我错了

Sub championshipforebet()
Dim objIE As Object
Dim itemEle As Object
Dim itemEle1 As Object
Dim away As Object
Dim desc As String, pt1 As String, pt2 As String, price As String
Dim i As Integer
Cells.Select
Selection.ClearContents
Selection.NumberFormat = "@"
Set objIE = CreateObject("internetexplorer.application")
objIE.Visible = True
objIE.navigate "https://www.forebet.com/it/"
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
Set itemEle = objIE.document.getElementsByClassName("moduletable_foremenu")(1)
Set itemEle1 = itemEle.getElementsByClassName("tree_foremenu")
i = 1
For Each ele1 In itemEle1(0).getElementsByTagName("li")
    i = i + 1
    Cells(i, 1) = ele1(0).getElementsByClassName("mainlevel_foremenu").href
Next ele1


End Sub

【问题讨论】:

    标签: html vba web-scraping nested screen-scraping


    【解决方案1】:

    虽然两个答案之间没有显着差异,但我决定发布我的答案,因为我已经创建了一个。 for loop 部分和 split 函数可能对未来的读者有所帮助。正如 QHarr 已经描述过的 .querySelector() 我没有重复同样的内容。

    这也是你可以尝试的代码:

    Sub GrabLinks()
        Const Baseurl$ = "https://www.forebet.com"
        Dim S$, I&
    
        With New XMLHTTP60
            .Open "GET", Baseurl & "/", False
            .send
            S = .responseText
        End With
    
        With New HTMLDocument
            .body.innerHTML = S
            With .querySelectorAll(".mainlevel_foremenu,.sublevel_foremenu")
                For I = 0 To .Length - 1
                    Cells(I + 1, 1) = Baseurl & Split(.Item(I).getAttribute("href"), "about:")(1)
                Next I
            End With
        End With
    End Sub
    

    添加到库的参考:

    Microsoft XML, v6.0
    Microsoft HTML Object Library
    

    【讨论】:

    • 非常感谢两位,但我不希望有人为我做这件事,但他告诉我我错在哪里而不需要太多更改我的脚本,因为我不需要一个脚本有效,但我理解,因为我喜欢并且我正在学习使用 vba 进行数据抓取
    • 如果您是来重新学习的,那么您找错了网站。如果您对此了解最少,那么QHarr 在他的帖子中描述的方式就足够了。但是,您可以check out this link to a video tutorial 以您期望的方式学习。
    • 如果你只是为了好玩而学习这个,可以考虑使用 Python 和 R 来抓取网站。我认为这两种技术在这类事情上都要优越得多。 srome.github.io/…bradleyboehmke.github.io/2015/12/scraping-html-tables.html
    【解决方案2】:

    您可以使用包括 OR 运算符 "," 的 css 选择器。此外,使用XMLHTTPRequest (XHR) 检索数据比打开 IE 快得多。


    链接属于两个类之一:

    顶层有类:

    mainlevel_foremenu
    

    嵌套的有类:

    sublevel_foremenu
    


    您可以使用 CSS 选择器组合来获取具有这两个类中的任何一个的所有元素,并将它们与 OR 运算符组合。

    a.mainlevel_foremenu,a.sublevel_foremenu
    

    a 表示 a 标记 (element selector),.class selector。因此,带有a 标签的元素具有类名mainlevel_foremenu,或(","sublevel_foremenu。在这种情况下,a 实际上并不是必需的,因此您可以缩短为 .mainlevel_foremenu, .sublevel_foremenu

    CSS 选择器返回多个项目,因此document.querySelectorAll 方法用于返回nodeList。然后迭代nodeList 的长度以按索引访问各个链接。

    链接是相对的,因此Replace 函数用于删除"about:",并且基本路径以链接地址为前缀。


    如果我们看一下页面上的第一个开关:

    组合的 CSS 选择器结果表明我们也获得了嵌套级别(注意我已经删除了一些中间结果)。


    VBA:

    Option Explicit
    Public Sub GetInfo()
        Application.Screenupdating = False
        Dim sResponse As String, i As Long, html As New HTMLDocument
        With CreateObject("MSXML2.XMLHTTP")
            .Open "GET", "https://www.forebet.com/", False
            .send
            sResponse = StrConv(.responseBody, vbUnicode)
        End With
        sResponse = Mid$(sResponse, InStr(1, sResponse, "<!DOCTYPE "))
        Dim links As Object
        With html
            .body.innerHTML = sResponse
            Set links = .querySelectorAll("a.mainlevel_foremenu,a.sublevel_foremenu")
        End With
        For i = 0 To links.Length - 1
            Cells(i + 1, 1) = "https://www.forebet.com" & Replace$(links(i).href, "about:", vbNullString)
        Next i
        Application.Screenupdating = True
    End Sub
    

    示例结果:


    参考资料(VBE > 工具 > 参考资料):

    1. Microsoft HTML 对象库

    【讨论】:

    • @ryguy72 说得好。谢谢。
    • @plinius - 我上面的回答中应该有足够的信息,以便您确定脚本需要修改的地方。我已经强调了您需要定位的内容。我可能会使用不同的访问方法,但其余部分完全相同。有两种不同的类需要处理,而你只看一个几乎就是简单的答案。我的解决方案是使用 OR 运算符来处理感兴趣的两种情况。
    猜你喜欢
    • 2014-05-11
    • 1970-01-01
    • 2021-10-08
    • 2019-07-23
    • 1970-01-01
    • 2020-11-21
    • 2019-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多