【问题标题】:Excel-VBA: buttons and drop-down lists before scraping data on .aspx web pagesExcel-VBA:在 .aspx 网页上抓取数据之前的按钮和下拉列表
【发布时间】:2018-01-13 17:46:50
【问题描述】:

我想使用 VBA 从网页中获取表格,但我无法直接访问它,因为我需要从一个选项卡切换到另一个选项卡。问题取决于网页的 .aspx 结尾(URL 没有相应地演变)。

网址:http://www.morningstar.fr/fr/fundquickrank/default.aspx

Default page after clicking URL

Moving to "Long Terme" Tab - URL won't change

我已经设法构建了将表格导出到 Excel 工作表的代码,但缺少“导航”部分。

这是关于单击“长期选项卡”按钮的 HTML 代码:

HTML Code Long Terme Tab

我的起点在这里(ProcessHTMLPage 做表格抓取):

Sub Browse_Morningstar()

Dim XMLPage As New MSXML2.XMLHTTP60
Dim HTMLDoc As New MSHTML.HTMLDocument


XMLPage.Open "GET", "http://www.morningstar.fr/fr/fundquickrank/default.aspx", False
XMLPage.send

HTMLDoc.body.innerHTML = XMLPage.responseText


ProcessHTMLPage HTMLDoc

End Sub

我想必须以某种方式更新请求。 抱歉,如果我不够准确,但我对这一切有点陌生。

非常感谢大家!

【问题讨论】:

  • 你试过下面的答案吗?

标签: html vba excel web-scraping


【解决方案1】:

__doPostBack 和 onclick 事件:

当您检查与选择主要内容 div 栏相关的 HTML 时,例如Long Terme,您可以看到有一个 java 脚本 __doPostBack function 与各个条形项目的 onclick 事件相关联。

观察有问题的 HTML:

引用我上面的链接:

该函数接受以下两个参数:

eventTarget - 这包含导致 回帖。 eventArgument - 这包含任何附加数据 与控件相关联。

在任何 ASP.NET 页面中,两个隐藏字段:__EVENTTARGET 和 __EVENTARGUMENT 是自动声明的。当页面回发到服务器时,ASP.NET 检查 __EVENTTARGET 和 __EVENTARGUMENT 值,这样它就可以决定是哪个控件导致了 要回发的页面以及必须处理的事件。

tldr;

ASP 的“旧”时代,通常必须有一个表单来捕获用户输入,然后创建更多页面来接受这些输入(GETPOST)、验证、执行操作等.使用ASP.NET,您可以在服务器上声明接受上述参数的控件,并在检查

的值后发回同一页面

第一个参数告诉您哪个控件被触发,第二个参数提供附加信息,在这种情况下决定返回哪些选项卡信息。

我们可以从上面看到TabAction 是控件,它后面的数字对应于感兴趣的选项卡,例如2 表示长期(作为 0 - 索引)。

在 VBA 中,我们可以通过多种方式执行这个 JS 函数,但我会使用:

.document.parentWindow.execScript "__doPostBack('EVENTTARGET', 'EVENTARGUMENT')"

这就变成了:

.document.parentWindow.execScript "__doPostBack('TabAction', '2')"

我重写它以接受 EVENTARGUMENT 作为常量 OPTION_CHOSEN,因此可以通过更改顶部的值来检索不同的选项卡。

执行该函数后,还有一点时间刷新页面,然后表格被其id抓取:

Set hTable = .document.getElementById("ctl00_ctl00_MainContent_Layout_1MainContent_gridResult")

然后表格沿着它的行和列循环(列是沿着每行长度的表格单元格)。


页面示例:


代码输出示例:


完整代码:

Option Explicit
Public Sub GetTable()
    Dim IE As New InternetExplorer
    Const OPTION_CHOSEN As Long = 2             '0 Aperçu; 1 Court terme; 2 Long terme; 3 Portefeuille; 4 Frais & Détails

    Application.ScreenUpdating = True
    With IE
        .Visible = True
        .navigate "http://www.morningstar.fr/fr/fundquickrank/default.aspx"
        While .readyState < 4: DoEvents: Wend

        .document.parentWindow.execScript "__doPostBack('TabAction', ' " & OPTION_CHOSEN & "')"

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

        Dim hTable As HTMLTable, tRow As HTMLTableRow, tCell As HTMLTableCell

        Set hTable = .document.getElementById("ctl00_ctl00_MainContent_Layout_1MainContent_gridResult")
        Dim c As Long, r As Long
        With ActiveSheet
            For Each tRow In hTable.Rows
                For Each tCell In tRow.Cells
                    c = c + 1: .Cells(r + 1, c) = tCell.innerText
                Next tCell
                c = 0: r = r + 1
            Next tRow
            .Columns("A:A").Delete
            .UsedRange.Columns.AutoFit
        End With
        .Quit
    End With
    Application.ScreenUpdating = True
End Sub

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

  1. Microsoft Internet 控件

【讨论】:

  • 嘿,你能看看我的问题吗? stackoverflow.com/questions/52618357/… 我会在 11 小时内添加赏金
  • 将在几分钟后查看
  • 嘿,对不起,当然是这样。将此代码用于我的一个自动机,稍作修改,但此版本也可以正常工作。非常感谢)
  • 嘿,对不起,我弄糊涂了。这不是我的主题。我让你看看我在 cmets 中的线程,你帮我解决了我的问题。我确实接受了那里的答案
  • 我以为你做了@lalachka :-)
【解决方案2】:
Sub Get_Info()

Dim Elems, e As Variant

Const READYSTATE_COMPLETE& = 4&
Dim ie As Object
Set ie = Nothing
DoEvents

Set ie = CreateObject("InternetExplorer.Application")
DoEvents

With ie
    .Visible = True
    .Navigate "http://www.morningstar.fr/fr/fundquickrank/default.aspx"
    While Not .readyState = READYSTATE_COMPLETE
        DoEvents
    Wend
End With

With ie.Document
    Set Elems = .getElementsByTagName("span")
    DoEvents
    For Each e In Elems
        If e.getAttribute("onclick") = "__doPostBack('TabAction', '2')" Then
            e.Click
            'try to insert your table export code here
            Exit For
        End If
    Next e

End With

Set Elems = Nothing
Set e = Nothing

'ie.Quit Quit Internet Explorer once the exporting is done
Set ie = Nothing

MsgBox "Done"
End Sub

上面的代码直接导航到您想要的标签。尝试将它与您的代码结合起来导出表格,也许它会起作用。 ie.Visible=True 只是为了确保您导航到正确的 URL,但是一旦您看到它有效,就将其设为 false。希望对您有所帮助!

【讨论】:

  • 谢谢,它将我重定向到正确的页面。但是,我无法设法“保存”重定向以导出数据(简而言之,它仍然是被抓取的欢迎页面)。而且我不知道如何更新 IE 以便它保留内存中的最后一条路径。
【解决方案3】:

如果您希望使用 IE 从该目标页面获取表格数据,那么这是实现该目标的一种方法。

Sub Fetch_Data()
    Dim IE As New InternetExplorer, html As HTMLDocument
    Dim posts As Object, post As Object, elem As Object, trow As Object

    With IE
        .Visible = True
        .navigate "http://www.morningstar.fr/fr/fundquickrank/default.aspx"
        While .readyState < 4: DoEvents: Wend
        Set html = .document
    End With

    For Each post In html.getElementsByClassName("ms_tab_inactivetext")
        If InStr(post.innerText, "Long terme") > 0 Then post.ParentNode.Click: Exit For
    Next post

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

    Set posts = html.getElementById("ctl00_ctl00_MainContent_Layout_1MainContent_gridResult")

    For Each elem In posts.Rows
        For Each trow In elem.Cells
            c = c + 1: Cells(r + 1, c) = trow.innerText
        Next trow
        c = 0: r = r + 1
    Next elem
    IE.Quit
End Sub

添加到库的参考:

1. Microsoft HTML Object Library
2. Microsoft Internet Controls

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 2017-05-10
    • 2020-12-05
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多