【问题标题】:Trouble selecting a single table using selenium使用 selenium 选择单个表时遇到问题
【发布时间】:2017-05-21 18:42:15
【问题描述】:

我尝试使用 selenium 从网页中抓取表格数据。但是,它会解析该页面中的所有表,但我需要一个。我找不到关于如何选择单个表格的任何想法。这是我尝试过的:

Sub table_data()
    Dim driver As New WebDriver
    Dim tabl As Object, rdata As Object, cdata As Object

    Set driver = New WebDriver
    driver.Start "Phantomjs", "https://fantasy.premierleague.com"
    driver.get "/player-list/"
    For Each tabl In driver.FindElementsByXPath("//table[@class='ism-table']")
        For Each rdata In tabl.FindElementsByXPath(".//tr")
            For Each cdata In rdata.FindElementsByXPath(".//td")
            y = y + 1
            Cells(x, y) = cdata.Text
            Next cdata
            x = x + 1
            y = 0
        Next rdata
    Next tabl
End Sub

不过,我是用 XHR 做到的!

Sub TableData()
Dim xmlpage As New XMLHTTP60
Dim htmldoc As New MSHTML.HTMLDocument
Dim htmlas As Object, tRow As Object, tCel As Object

x = 1
With xmlpage
    .Open "GET", "https://fantasy.premierleague.com/player-list/", False
    .send
    htmldoc.body.innerHTML = .responseText
End With
Set htmlas = htmldoc.getElementsByTagName("table")(2)
For Each tRow In htmlas.Rows
    For Each tCel In tRow.Cells
        c = c + 1
        Cells(x, c) = tCel.innerText
    Next tCel
    c = 0
    x = x + 1
Next tRow
End Sub

【问题讨论】:

  • 你需要哪张桌子?你不能用索引得到它吗?
  • 感谢 PRAISER 的回答。外面有八张桌子。任何人都会做。在索引的情况下,我不明白我应该把那个数字放在我的代码中的什么地方?

标签: vba selenium web-scraping


【解决方案1】:

一旦第一个表的行完成,您就可以简单地打破 ForEach 循环

Sub table_data()
    Dim driver As New WebDriver
    Dim tabl As Object, rdata As Object, cdata As Object

    Set driver = New WebDriver
    driver.Start "Phantomjs", "https://fantasy.premierleague.com"
    driver.get "/player-list/"
    For Each tabl In driver.FindElementsByXPath("//table[@class='ism-table']")
        For Each rdata In tabl.FindElementsByXPath(".//tr")
            For Each cdata In rdata.FindElementsByXPath(".//td")
            y = y + 1
            Cells(x, y) = cdata.Text
            Next cdata
            x = x + 1
            y = 0
        Next rdata
        Goto end_of_for
    Next tabl
    end_of_for:
End Sub

或者只是获取FindElementsByXPath 的第一个元素,因为driver.FindElementsByXpath(....)(0) 应该返回第一个元素。

--(编辑)

根据this docs,您应该能够通过Items 获得正确的值,因此它将是driver.FindElementsByXpath(....).Item(4)

【讨论】:

  • 感谢 PRAISER 的回答。这种方法对我来说是新事物。它确实解析了第一个表。但是,如果我想解析第四个表,我可以在您上面应用的方法中进行哪些更改?仅供参考,索引显示错误。如果我能应用你的第二种方法那就太棒了!
  • 你是一个男人兄弟的宝石。脱帽致敬。你让我今天一整天都感觉很好。顺便说一句,该行应该是 [Set tabl = driver.FindElementsByXPath("//table[@class='ism-table']").Item(1)]
  • 最后一件事要敦促:如果我尝试你的第一种方法,是否可以选择任何特定的表?很想知道。谢谢你的一切。
  • 是的,只需将Goto 放在循环开头的下一个ForEach 之前,并添加一个条件以确保索引是正确的。但是您需要通过在第一个循环之外声明它来跟踪索引。
  • 感谢一万亿的一切。您的索引方法(使用 Item 属性)也适用于常规 vba。我希望我能多次点击赞成按钮。
【解决方案2】:

实际上你可以通过 XHR 和 Split 做到这一点,不需要使用 Selenium。看看下面的代码:

Option Explicit

Sub Scrape_premierleague_com()

    Dim sResponse, j, i, aRows, aCells

    With CreateObject("MSXML2.XMLHTTP")
        .Open "GET", "https://fantasy.premierleague.com/player-list/", False
        .Send
        sResponse = .responseText
    End With
    ThisWorkbook.Sheets(1).Cells.Delete
    sResponse = Split(Split(sResponse, "<tbody>")(1), "</tbody>", 2)(0) ' 1 - number of the table
    aRows = Split(sResponse, "<tr>")
    For j = 1 To UBound(aRows)
        aCells = Split(aRows(j), "<td>")
        For i = 1 To UBound(aCells)
            ThisWorkbook.Sheets(1).Cells(j, i).Value = Split(aCells(i), "</td>", 2)(0)
        Next
    Next
    ThisWorkbook.Sheets(1).Columns.AutoFit

End Sub

这是我的输出:

【讨论】:

  • 感谢 omegastripes 先生,为您提供甜蜜而美好的解决方案。实际上,我一开始就使用 XHR。我需要知道如何解析表格,以防它在 javascript 中被加密,并且直到现在我从未尝试使用 selenium 解析表格。上述地点是一个标本。但是,您的风格与众不同且简洁。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-21
  • 2019-09-10
  • 1970-01-01
  • 2014-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多