【问题标题】:Can MSXML2.XMLHTTP retrieve ALL of the HTML data for a given webpage?MSXML2.XMLHTTP 可以检索给定网页的所有 HTML 数据吗?
【发布时间】:2019-01-13 13:32:01
【问题描述】:

对于显示检索数据表的动态网页,我发现 MSXML2.XMLHTTP 和 Internet Explorer 对象通常都无法访问这些数据。一个很好的例子是https://www.tiff.net/tiff/films.html。这两种技术都不会检索任何电影数据——只是周围的网页。我试过的代码如下:

Function getHTTP(ByVal sReq As String) As Variant
    On Error GoTo onErr
    With CreateObject("MSXML2.XMLHTTP")
        .Open "GET", sReq, False
        .send
        getHTTP = StrConv(.responseBody, 64)
    End With
    Exit Function
    onErr:   MsgBox "Error " & Err & ": " & Err.Description, 49, "Error opening site"
End Function

Function GetHTML(ByVal strURL As String) As Variant
  Dim oIE As InternetExplorer
  Dim hElm As IHTMLElement
  Set oIE = New InternetExplorer
  oIE.Navigate strURL
  Do While (oIE.Busy Or oIE.ReadyState <> READYSTATE_COMPLETE)
     DoEvents
  Loop
  Set hElm = oIE.Document.all.tags("html").Item(0)
  GetHTML = hElm.outerHTML
  Set oIE = Nothing
  Set hElm = Nothing
End Function

但有一种方法可以手动检索电影数据 - 只需使用 Microsoft Edge 或 Internet Explorer 按照以下步骤操作:

Right-click on one of the movies 

Choose “inspect element." The DevTools console opens. 

At the bottom-left of the screen, click on the “html” tab. 

Right-click the tab.  Choose “copy.” 

Open notepad and paste what you’ve copied.

您现在有了电影数据,可以将其保存到文件中进行解析。我的问题:有没有办法以编程方式获取这些数据?

【问题讨论】:

  • 有趣的问题+1

标签: html vba ms-access web-scraping


【解决方案1】:

为什么是 Json?因为页面是使用 json 数据加载的

查看:使用谷歌浏览器 --> 按 F12 --> 加载 URL --> 转到网络选项卡


代码:

Sub getHTTP()

    Dim Url As String, data As String
    Dim xml As Object, JSON As Object, colObj, item


    Url = "https://www.tiff.net/data/films-events-2018.json?q=1513263947586"

    Set xml = CreateObject("MSXML2.ServerXMLHTTP")
    With xml
        .Open "GET", Url, False
        .send
        data = .responseText
    End With


    Set JSON = JsonConverter.ParseJson(data)
    Set colObj = JSON("items")

    For Each item In colObj
        Debug.Print item("title")
        Debug.Print item("description")

        For Each c1 In item("cast")
            Debug.Print c1
        Next

        For Each c2 In item("countries")
            Debug.Print c2
        Next
    Next
End Sub

输出


安装JsonConverter

  1. 下载latest release
  2. 将 JsonConverter.bas 导入您的项目(打开 VBA 编辑器,Alt + F11;文件 > 导入文件) 添加字典参考/类
  3. 仅适用于 Windows,包括对“Microsoft Scripting Runtime”的引用
  4. 对于 Windows 和 Mac,包括 VBA 字典

数据树状视图

【讨论】:

  • 感谢您提供所有这些出色的建议——尤其是 JSON。我已经开始玩它并且喜欢我所看到的。我只是有几个问题: 1. 你是从哪里想到“tiff.net/data/films-events-2018.json?q=1513263947586”的? 2. 为什么colobj中只有标题和描述? “演员”和“国家”之类的东西也应该可用,但是如果您尝试使用您选择的两个以外的任何东西,程序会给您一个错误。 3. 在locals窗口哪里可以看到title和description的值?
  • 很高兴你喜欢它。 1. Http 观察窗口显示网站是使用 json 数据加载的 2. 因为它们是集合,所以需要循环(见树形视图)
  • 好答案 + 1
  • 好的,我到了!我终于发现了 CQZpR.jpg 页面。您(或任何人)能否确认当前记录中的数据实际上在本地窗口的任何地方都看不到?您的那个例程需要将 C1 和 C2 声明为变体。即使那样,我也无法分配检索到的值……只能打印它。我不得不从 MSXML2.ServerXMLHTTP 中取出“服务器”,然后它就起作用了。所以现在看起来我在做生意!感谢您提供一流的帮助。这是我在技术论坛上收到的信息量最大的回复之一,这说明了一些事情!
  • 1.是的,C1 和 C2 应该声明为变体 2。数据在本地窗口中可见
【解决方案2】:

这是使用 IE 的电影片名(您可以使用相同的流程来获取导演)

Option Explicit
Public Sub GetFilms()
    Dim IE As New InternetExplorer, html As HTMLDocument, films As Object, i As Long
    With IE
        .Visible = True
        .navigate "https://www.tiff.net/tiff/films.html"

        While .Busy Or .readyState < 4: DoEvents: Wend
        Set films = .document.querySelectorAll("[target=_self]")

        For i = 0 To films.Length - 1
            Debug.Print films.item(i).innerText
        Next
        .Quit '<== Remember to quit application
    End With
End Sub

XHR 太快了,有提供的 URL,但是 IE 就可以了。

如果您检查 HTML,您会发现每部电影都有以下共同点:

a 标记中有一个名为target 的属性,其值为_self

您可以使用属性 CSS 选择器通过 document.querySelectorAll 方法收集所有这些匹配元素


CSS 选择器(示例):


如果可以通过解析 HTML 来获取电影描述,我会很感兴趣。我原以为 cmets 的存在掩盖了电影的描述。理论上,在"&lt;!-- react-text: \d+ --&gt;([^...].+?(?=&lt;))" 中选择文本的正则表达式在应用于.innerHTML 时似乎失败了,尝试用正则表达式开始和结束评论也是如此。

【讨论】:

  • 你能告诉我如何使用你的例程来获取除标题之外的其他字段吗?我无法在本地窗口中观察“电影”,如果单击它,程序会冻结然后崩溃。你可以在这个线程中看到 Santosh 的变量窗口和我的……我如何得到他的?
  • 这是 Excel 的一个错误,您无法在本地窗口中展开静态 nodeList(或使用 For Each 进行迭代),这就是 querySelectorAll 返回的内容。见here
  • 在过去的几个月里,.querySelector() 在 vba 中使用它时得到了极大的欢迎(实际上应该如此)。您是值得称赞@QHarr 的贡献者之一。
  • @SIM 你介绍给我的!很遗憾,CSS 选择器比我们在 VBA 中可以使用的要多得多:-(
  • 哦,是的!那是因为伪选择器。如果我们有范围可以使用它,那么 vba 在进行抓取时会达到一个新的水平。
猜你喜欢
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-23
  • 2019-12-10
相关资源
最近更新 更多