VBA网络抓取,将HTML文本转换为Excel:如何在忽略父元素的同时提取子元素?

时间:2018-11-08 00:34:08

标签: excel vba excel-vba

我是一个初学者,正在尝试从html表做基本的webscrape,以精益求精,并努力解决特定的网站设计问题。据我了解,大多数表都是用这样的标签来组织的:(table-> tr-> td)像这样,先是表,然后是行,然后是单元格。

我可以很轻松地处理它,但是试图从中提取的“主表”具有包含在单元格内的表和行,例如(“主表->行->单元格->子表- > sub-row-> sub-cell)。为了我的一生,我无法获得一张干净的Excel工作表

这是html的样子:

detailed html

overview html

我需要做的是仅提取NCI$392,764。但是到目前为止,我正在使用.innertext命令提取这些值的重复项。我希望有人可以帮助我编写一个简单的宏,该宏仅从每个父单元格中抓取lastchild元素...谢谢!

这是我到目前为止所拥有的...

这是麻烦所在:

Sub processhtmlpage(htmlpage As mshtml.HTMLDocument)

Dim htmlTable As mshtml.IHTMLElement
Dim htmlTables As mshtml.IHTMLElementCollection
Dim HTMLRow As mshtml.IHTMLElement
Dim htmlrows As mshtml.IHTMLElementCollection
Dim htmlcell As mshtml.IHTMLElement
Dim rownum As Long, colnum As Integer


Set htmlTables = htmlpage.getElementsByTagName("table")
Set HTMLInnerTables = htmlpage.getElementsByTagName("table")
Set HTMLInnerRows = htmlpage.getElementsByTagName("tr")


    For Each htmlTable In htmlTables
        Worksheets.Add
        Range("a1").Value = htmlTable.className
        Range("b1").Value = Now
        rownum = 2
            For Each HTMLRow In htmlTable.getElementsByTagName("tr")
            colnum = 1
                For Each htmlcell In HTMLRow.getElementsByTagName("td")
                    Cells(rownum, colnum) = htmlcell.innerText
                    colnum = colnum + 1
                Next htmlcell
                rownum = rownum + 1
            Next HTMLRow
    Next htmlTable
End Sub

我已经通过使用if ... then命令进行了一些疯狂的尝试来规避此问题,但是几个小时后,我完全迷失了。必须有一个更好的方法。请帮忙!!!如果有帮助,这里是集群****,我最后得到了:

Sub processhtmlpage(htmlpage As mshtml.HTMLDocument)

Dim htmlTable As mshtml.IHTMLElement
Dim htmlTables As mshtml.IHTMLElementCollection
Dim HTMLRow As mshtml.IHTMLElement
Dim htmlrows As mshtml.IHTMLElementCollection
Dim htmlcell As mshtml.IHTMLElement
Dim rownum As Long, colnum As Integer
Dim HTMLInnerTables As mshtml.IHTMLElementCollection
Dim HTMLInnerTable As mshtml.IHTMLElement
Dim HTMLInnerRow As mshtml.IHTMLElement
Dim HTMLInnerows As mshtml.IHTMLElementCollection
Dim innerhtmlcell As mshtml.IHTMLElement

Set htmlTables = htmlpage.getElementsByTagName("table")
Set HTMLInnerTables = htmlpage.getElementsByTagName("table")
Set HTMLInnerRows = htmlpage.getElementsByTagName("tr")

    For Each htmlTable In htmlTables
        If htmlTable.getAttribute("id") <> "main-table" Then
        GoTo line4
        End If

        Worksheets.Add
        Range("a1").Value = htmlTable.className
        Range("b1").Value = Now
        rownum = 2

            For Each HTMLRow In htmlTable.getElementsByTagName("tr")
                If HTMLRow.getAttribute("bgcolor") = "#ffffff" Or HTMLRow.getAttribute("class") = "lop" Then
                    GoTo line6
                End If
                colnum = 1

              For Each htmlcell In HTMLRow.getElementsByTagName("td") [line 6]
                        If htmlcell.getAttribute("nowrap") = "nowrap" Then
                        GoTo line1
                        Else
                        If htmlcell.getAttribute("colspan") = 2 Then
                            Cells(rownum, colnum) = htmlcell.innerText
                            rownum = rownum + 1
                            Call stupidcell
                            Else
                        End If
                        For Each HTMLInnerTable In htmlcell.getElementsByTagName("table")
                            If HTMLInnerTable.getAttribute("id") <> "main-table" Then
                                GoTo line1
                            End If
                        Next HTMLInnerTable
                            For Each HTMLInnerRow In htmlcell.getElementsByTagName("tr")
                                If HTMLInnerRow.getAttribute("bgcolor") = "#ffffff" Then
                                    GoTo line1
                                End If
                            Next HTMLInnerRow [line5]
                        Next HTMLInnerTable
                        Cells(rownum, colnum) = htmlcell.innerText [line2]
                        colnum = colnum + 1
                    Next htmlcell [line1]
                    rownum = rownum + 1
            Next HTMLRow [line3]
        Next htmlTable [line4]
End Sub

3 个答案:

答案 0 :(得分:1)

这不是不是答案,因此可能会被标记出来,但这是留下包括图形在内的评论的唯一方法,因此可能是S.O。上帝会让它滑动(否则,我就删除!)


当我有一组复杂的嵌套For / If时,我将其复制到文本编辑器(最好是Notepad ++),然后删除除嵌套部分外的所有代码,并对其进行整理,这样我就可以知道问题出在哪里。

第一个过程正确嵌套:
img

第二个过程有一个问题,用红色表示:
img

您要为For关闭两次HTMLInnerTable

答案 1 :(得分:1)

从表中提取文本是一个非常基本的开始-您只需要定位目标单元格并对文本进行一些清理即可。

绝对不是“ Web标准”方法,但有时粗略而易于使用的方法更易于管理,并且页面布局的微小更改可能会破坏整个事情,这太有意义了。

Sub NIHTable()

    Dim htmlpage, tbl, rw, cl, rownum, cellNum

    'populate htmlpage

    Set tbl = htmlpage.document.getElementById("main-table")
    rownum = 0
    For Each rw In tbl.Rows
        rownum = rownum + 1
        Debug.Print "------ Row# " & rownum
        cellNum = 0
        For Each cl In rw.Cells
            cellNum = cellNum + 1
            Debug.Print , cellNum, Trim(Replace(cl.innerText, vbCrLf, ";"))
        Next cl
    Next rw

End Sub

示例行输出:

------ Row# 9
               1            
               2            1 R43 CA23616401
               3            
               4            DEVELOPMENT OF TARGETED, SAFE AND EFFECTIVE DRUGS AGAINST PANCREATIC DUCTAL ADENOCARCINOMA (PDAC) BY LEVERAGING A NOVEL, COMPREHENSIVE, COMPUTATIONAL DRUG DISCOVERY APPROACH
               5            HEUER, TIM S.
               6            TWOXAR, INC.
               7            2018
               8            NCI
               9            ,NCI ,,$225,030
               10           

答案 2 :(得分:0)

没有实际使用的HTML尚未经过测试。我尤其看不到其他哪些元素可能与以下CSS选择器模式匹配。

您想要的商品有table个带标签的父母。更具体地说,它们位于具有属性td的类lop的子align元素中,该元素位于具有类tr的{​​{1}}元素中。使用如下的CSS后代组合器语法:

lop

您可以使用table tr.lop [align]td.lop 的{​​{1}}方法来收集与该模式匹配的元素,如下所示:

querySelectorAll

如果仍然存在重复值的问题,请考虑将检索到的值加载到字典中并在末尾将其清空

HTMLDocument