我在抓这个问题时遇到了麻烦

时间:2018-06-13 02:59:51

标签: excel vba excel-vba web-scraping

我试图理解为什么我的参考资料不能很好地抓取这些数据。

这是网站的一个例子:
http://quote.morningstar.ca/Quicktakes/Financials/is.aspx?t=GNTX&region=USA&culture=en-CA&ops=clear

作为目标:

<div id="data_i6" class="rf_crow"><div id="Y_1" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="741131269">741</div><div id="Y_2" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="836611464">837</div><div id="Y_3" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="939841654">940</div><div id="Y_4" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="1010472512">1,010</div><div id="Y_5" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="1100344312">1,100</div><div id="Y_6" class="pos column6Width_noChart116px" style="overflow:hidden;white-space: nowrap;" rawvalue="1115401551">1,115</div></div>

我需要提取的是rawvalue中的实际值=&#34; 741131269&#34;以下是我到目前为止所做的工作。

'Cells(1, 1) = Document.getElementsByClassName("rf_crow")'returns the rows of data into one cell
'Cells(1, 1) = Document.getElementById("Y_1").innerText 'returns the text for the year
'Cells(1, 1) = Document.getElementById("data_i1").innerText 'returns to first row of data

我知道上面的内容并没有返回我想要的内容,因为评论会告诉你它提取到Excel中的内容。子元素似乎不像我在其他构建的宏中那样工作。我觉得这样的事情会奏效:

Cells(1, 1) = Document.getElementById("Y_1").getAttribute("rawvalue")

但是,这也没有用,我试过了:

Cells(1, 1) = Document.getElementById("data_i6").getElementById("Y_1").innertext

那也不起作用。

4 个答案:

答案 0 :(得分:1)

解决方案非常简单。只需使用它的'rawvalue。

属性来调用它

您可以这样做:

使用Hardcoded delayfor loop检查所需值的可用性:

Sub GetValue()
    Dim IE As New InternetExplorer, HTML As HTMLDocument, post As Object, elem As Object

    With IE
        .Visible = True
        .Navigate "http://quote.morningstar.ca/Quicktakes/Financials/is.aspx?t=GNTX&region=USA&culture=en-CA&ops=clear"
        While .Busy = True Or .ReadyState < 4: DoEvents: Wend
        Set HTML = .Document
    End With

    ''using hardcoded delay
    Application.Wait Now + TimeValue("00:00:05")

    For Each elem In HTML.getElementsByTagName("div")
        If elem.innerText = "741" Then MsgBox elem.getAttribute("rawvalue"): Exit For
    Next elem
End Sub

使用Explicit Wait

Sub GetValue()
    Dim IE As New InternetExplorer, HTML As HTMLDocument, post As Object

    With IE
        .Visible = True
        .Navigate "http://quote.morningstar.ca/Quicktakes/Financials/is.aspx?t=GNTX&region=USA&culture=en-CA&ops=clear"
        While .Busy = True Or .ReadyState < 4: DoEvents: Wend
        Set HTML = .Document
    End With

    Do: Set post = HTML.querySelector("#data_i6 #Y_1"): DoEvents: Loop While post Is Nothing

    MsgBox post.getAttribute("rawvalue")
End Sub

此时输出:

741131269

答案 1 :(得分:0)

尝试将“objCollection”声明为对象,将strValue声明为字符串,并在下面的代码中,在第一行中替换您声明的http请求的名称:

Document.body.innerHTML = YourHTTPRequest.responseText
Set objCollection = Document.getElementsByClassName("rf_crow")

 For Each objElement In objCollection

     If objElement.ID = "Y_1" Then
         strValue = objElement.getAttribute("rawvalue")
         Exit For
     End If

 Next

 Cells(1, 1) = strValue

答案 2 :(得分:0)

以下内容应说明您遇到的一些问题。

<强> .querySelectorAll

您提到的确切元素是.document使用CSS选择器#Y_1的{​​{3}}方法返回的第二个索引。 .querySelectorAll表示Id。

从该网页返回以下内容(显示的示例 - 并非全部):

#

从上面你可以看到你想要的字符串是由结果中的索引2返回的。

querySelectorAll with Id? Id不是单个元素的唯一标识符吗?

这个ID出乎意料地并不是页面上单个元素所独有的。它发生了27次:

CSS query

这意味着您可以使用.querySelectorAll方法返回所有匹配项的nodeList,并使用索引2处的项来获取结果。

注意:

如果您想要rawvalue741131269旁边的长号,请解析返回元素的outerHTML

Debug.Print Replace(Split(Split(a.item(2).outerHTML, "rawvalue=")(1), ">")(0), Chr$(34), vbNullString)

<强> .querySelector

或者,您可以使用

定位特定data_i6的ID
.document.querySelector("#data_i6")

这个CSS选择器(#data_i6)返回每年的整行。如果使用.querySelector,您将只获得第一个项目,即第1年。

Id

您可以使用CSS选择器更具体,并添加额外的年份ID以获得感兴趣的年份:

#data_i6 #Y_1

By id all years

代码:(在querySelectorAll旁边注释掉querySelector方法)

Option Explicit
Public Sub Get_Information()
    Dim IE As New InternetExplorer

    With IE
        .Visible = True
        .navigate "http://quote.morningstar.ca/Quicktakes/Financials/is.aspx?t=GNTX&region=USA&culture=en-CA&ops=clear"
        While .Busy = True Or .readyState < 4: DoEvents: Wend

        Dim a As Object, exitTime As Date
        exitTime = Now + TimeSerial(0, 0, 2)

        Do
            DoEvents
            On Error Resume Next
            Set a = .document.querySelectorAll("#Y_1") ' .document.querySelector("#data_i6 #Y_1")
            On Error GoTo 0
            If Now > exitTime Then Exit Do
        Loop While a Is Nothing

        If a Is Nothing Then Exit Sub

        Debug.Print Split(Split(a.item(2).innerText, "rawvalue=")(0), ">")(0) 'Split(Split(a.innerText, "rawvalue=")(0), ">")(0)
        Debug.Print Replace(Split(Split(a.item(2).outerHTML, "rawvalue=")(1), ">")(0), Chr$(34), vbNullString) 'Replace(Split(Split(a.outerHTML, "rawvalue=")(1), ">")(0), Chr$(34), vbNullString)

        .Quit
    End With
End Sub

答案 3 :(得分:0)

这对您有用吗?

library(future.apply)