【问题标题】:Excel VBA Scraping li tags with the same class nameExcel VBA刮取具有相同类名的li标签
【发布时间】:2017-12-03 17:21:25
【问题描述】:

我正在尝试抓取具有相同类名的 li 标签 HTML 代码如下所示:

<ul class="top-section-list" data-selenium="highlightList">    
                <li class="top-section-list-item">sample text# 1</li>           
                <li class="top-section-list-item">sample text# 2</li>            
                <li class="top-section-list-item">sample text# 3</li>           
                <li class="top-section-list-item">sample text# 4</li>            
                <li class="top-section-list-item">sample text# 5</li>     
        </ul>

这是我的 VBA 代码,它只能抓取第一个列出的项目,而不是其余的。

    Sub GetData()

    Dim objIE As InternetExplorer
    Dim itemEle As Object
    Dim data As String
    Dim y As Integer

    Set objIE = New InternetExplorer
    objIE.Visible = True

    objIE.navigate "https://www.bhphotovideo.com/c/product/1312545-REG/fujifilm_16550643_instax_mini_9_instant.html"
    Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop

    For Each itemEle In objIE.document.getElementsByClassName("top-section-list")
    data = itemEle.getElementsByTagName("li")(0).innerText

    Next
    Range("A1").Value = data
End Sub

它只写入单元格 A1:“sample text# 1” 我怎样才能将所有标签写入单元格 A1? 所需的结果将是单元格 A1: 示例文本# 1 示例文本# 2 示例文本# 3 示例文本# 4 示例文本# 5

谢谢!

【问题讨论】:

  • data = Range("A1").Value如何将data字符串值写入单元格A1?
  • 应该是反过来的,我糊涂了
  • 好的,尽快回复您。

标签: html vba excel web-scraping


【解决方案1】:

使用.querySelectorAll 并遍历返回的nodeList

要使用的 CSS 选择器是

ul.top-section-list li

VBA 代码:

Option Explicit
Public Sub GetData()
    Dim objIE As InternetExplorer, nodeList As Object, currentItem As Long, outputString As String
    Set objIE = New InternetExplorer
    objIE.Visible = True
    objIE.navigate "https://www.bhphotovideo.com/c/product/1312545-REG/fujifilm_16550643_instax_mini_9_instant.html"

    Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop

    Set nodeList = objIE.document.querySelectorAll("ul.top-section-list li")
    With ActiveSheet                             '<== use actual sheet name
        For currentItem = 0 To nodeList.Length - 1
            outputString = outputString & Chr$(32) & nodeList.item(currentItem).innerText
        Next currentItem
        .Cells(1, 1) = Trim$(outputString)
    End With
    'ObjIE.Quit
End Sub

CSS 查询:

Try it

【讨论】:

    【解决方案2】:

    最简单的方法可能是这样的:

    Dim data As String
    Dim elem as object
    
    data = ""
    For Each elem In html.getElementsByClassName("top-section-list")(0).getElementsByTagName("li")
        data = data & " " & elem.innerText
    Next elem
    [A1] = data
    

    输出:

     sample text# 1 sample text# 2 sample text# 3 sample text# 4 sample text# 5 
    

    现在,试一试:

    Sub GetData()
        Dim IE As New InternetExplorer, html As HTMLDocument
        Dim elem As Object, data As String
    
        With IE
            .Visible = True
            .navigate "https://www.bhphotovideo.com/c/product/1312545-REG/fujifilm_16550643_instax_mini_9_instant.html"
            Do While .readyState <> READYSTATE_COMPLETE: Loop
            Set html = .document
        End With
    
        data = ""
    
        For Each elem In html.getElementsByClassName("top-section-list")(0).getElementsByTagName("li")
            data = data & " " & elem.innerText
        Next elem
    
        Range("A1").Value = data
    
        IE.Quit
    End Sub
    

    我已尝试改进您的代码,使其看起来略显悦目。

    添加到库的参考:

    Microsoft Internet Controls
    Microsoft HTML Object Library
    

    还有一件事:正如 Jeeped 指出的那样,如果你得到一个尾随空格,那么你可以尝试类似Range("A1").Value = Trim(Application.WorksheetFunction.Clean(data))

    【讨论】:

    • 您的示例输出显示一个空格字符(例如 Chr(32))作为分隔符,但您的代码没有添加一个。
    • 是的,这看起来很合适,但没有Trim(data),您仍然会有一个前导空格字符。由于我使用换行符作为分隔符,因此我选择了Mid(data, 2)
    • 嗨 Shahin,我收到“对象不支持此方法.. 我已经编辑了我的原始帖子以显示确切的网站,因此您可以通过这种方式对其进行测试。感谢您的所有帮助
    • @rkrox907 - Shahin 似乎用html 替换了objIE.document。除此之外,代码看起来应该可以工作。
    • 查看编辑。顺便说一句,您知道要向库中添加什么参考吗?
    【解决方案3】:

    使用 vbLF 分隔符将字符串值连接到 data 字符串 var。

    dim data as string, i as long
    data = vbNullString
    
    with objIE.document.getElementsByClassName("top-section-list")(0)
        For i = 0 to .getElementsByTagName("li").Length - 1
            data = data & vblLF & .getElementsByTagName("li")(i).innerText
        Next
    end with
    Range("A1").Value = Mid(data, 2)  'write data INTO A1, not the other way around
    

    【讨论】:

    • 嗨吉普德,我试过你的解决方案。我得到“对象不支持在线属性或方法” For i = 0 to .getElementsByTagName("li").Count - 1"
    • 我承认我是在脑海中写下代码; tbh,我没有时间设置甚至找到合适的 someWebsite 进行测试。也许您可以自己弄清楚;我知道该方法至少是有效的。
    • 好的,应该是.Length 而不是.Count
    • 是的,现在它工作了!用.Length TY!是否可以将每个 innerText 放在单独的一行中,而不是全部放在一行中?
    • vbLF 就是这样做的。这是一个“换行”。尝试在 A1 上使用 Wrap Text 格式。
    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多