当前位置: 首页 > 面试题库 >

使用VBA进行Web抓取(当HTML <> DOM时)

锺离鸿
2023-03-14
问题内容

我在抓取该特定网页的数据时经历了可怕的时间……
基本上,当我
在浏览器中加载URL并手动按F12键时,但是当我以编程方式
尝试执行此操作时,我可以在“ DOM Explorer”中看到所需的信息(参见下文)HTMLDoc不包含
我在“ DOM资源管理器”中看到的相同信息…

Public Sub testCode()

    Dim IE As SHDocVw.InternetExplorer
    Dim HTMLDoc As MSHTML.HTMLDocument
    Set IE = New SHDocVw.InternetExplorer
    With IE
        .navigate "https://www.wunderground.com/cgi-bin/findweather/getForecast?query=EIDW"
        While .Busy = True Or .ReadyState <> READYSTATE_COMPLETE: Wend
        Set HTMLDoc = .Document
    End With

End Sub

有人可以帮我访问“ DOM资源管理器”中的信息吗?我知道HTML并不总是您在浏览器中看到的,而是在浏器中创建可见内容的说明,但是必须有一种方法可以从HTML以编程方式创建DOM……

另外,我相信我是由脚本或生成后的数据iFrame中,但我一直无法生成我要寻找的数据从
瞎搞有两种....


问题答案:

大纲:

  • 使GET XHR到https://www.wunderground.com/cgi-bin/findweather/getForecast?query=EIDW。

  • 从HTML响应行中提取位置,var query = ‘zmw:’ + ‘00000.271.03969’;并从这些行中提取键var citypage_options = {k: ‘c991975b7f4186c0’, …。

  • 使用位置让GET XHR 00000.271.03969和密钥c991975b7f4186c0来https://api-ak-aws.wunderground.com/api/c991975b7f4186c0/forecast10day/hourly10day/labels/conditions/astronomy10day/lang:zh-CN/units:metric/v:2.0/bestfct:1/q/zmw:00000.271。 03969.json。

  • 使用解析JSON响应(例如,使用VBAJSON解析器),使用Parse()转换所需的数据ToArray(),并作为表格输出到工作表。

实际上,每次打开该网页时,Web浏览器都会执行几乎相同的操作。

您可以使用下面的VBA代码来解析响应并输出结果。将JSON.bas模块导入VBA项目以进行JSON处理。

Sub TestScrapeWunderground()

    Dim sContent As String
    Dim sKey As String
    Dim sLocation As String
    Dim vJSON As Variant
    Dim sState As String
    Dim oDays As Object
    Dim oHours As Object
    Dim vDay As Variant
    Dim vHour As Variant
    Dim aRows() As Variant
    Dim aHeader() As Variant

    ' GET XHR to retrieve location and key
    With CreateObject("MSXML2.ServerXMLHTTP")
        .Open "GET", "https://www.wunderground.com/cgi-bin/findweather/getForecast?query=EIDW", False
        .Send
        sContent = .responseText
    End With
    ' Extract location and key from HTML content
    sLocation = Split(Split(sContent, "var query = 'zmw:' + '", 2)(1), "'", 2)(0)
    sKey = Split(Split(sContent, vbTab & "k: '", 2)(1), "'", 2)(0)
    ' GET XHR to retrieve JSON data
    With CreateObject("MSXML2.ServerXMLHTTP")
        .Open "GET", "https://api-ak-aws.wunderground.com/api/" & sKey & "/forecast10day/hourly10day/labels/conditions/astronomy10day/lang:en/units:metric/v:2.0/bestfct:1/q/zmw:" & sLocation & ".json", False
        .Send
        sContent = .responseText
    End With
    ' Parse JSON response to data structure
    JSON.Parse sContent, vJSON, sState
    ' Populate dictionaries with daily and hourly forecast data
    Set oDays = CreateObject("Scripting.Dictionary")
    Set oHours = CreateObject("Scripting.Dictionary")
    For Each vDay In vJSON("forecast")("days")
        oDays(vDay("summary")) = ""
        For Each vHour In vDay("hours")
            oHours(vHour) = ""
        Next
    Next
    ' Convert daily forecast data to arrays
    JSON.ToArray oDays.Keys(), aRows, aHeader
    ' Output daily forecast data to table
    With Sheets(1)
        .Cells.Delete
        OutputArray .Cells(1, 1), aHeader
        Output2DArray .Cells(2, 1), aRows
        .Columns.AutoFit
    End With
    ' Convert hourly forecast data to arrays
    JSON.ToArray oHours.Keys(), aRows, aHeader
    ' Output hourly forecast data to table
    With Sheets(2)
        .Cells.Delete
        OutputArray .Cells(1, 1), aHeader
        Output2DArray .Cells(2, 1), aRows
        .Columns.AutoFit
    End With
    ' Convert response data to arrays
    JSON.ToArray Array(vJSON("response")), aRows, aHeader
    ' Output response transposed data to table
    With Sheets(3)
        .Cells.Delete
        Output2DArray .Cells(1, 1), WorksheetFunction.Transpose(aHeader)
        Output2DArray .Cells(1, 2), WorksheetFunction.Transpose(aRows)
        .Columns.AutoFit
    End With
    ' Convert current data to arrays
    JSON.ToArray Array(vJSON("current_observation")), aRows, aHeader
    ' Output current transposed data to table
    With Sheets(4)
        .Cells.Delete
        Output2DArray .Cells(1, 1), WorksheetFunction.Transpose(aHeader)
        Output2DArray .Cells(1, 2), WorksheetFunction.Transpose(aRows)
        .Columns.AutoFit
    End With
    ' Populate dictionary with daily astronomy data
    Set oDays = CreateObject("Scripting.Dictionary")
    For Each vDay In vJSON("astronomy")("days")
        oDays(vDay) = ""
    Next
    ' Convert daily astronomy data to arrays
    JSON.ToArray oDays.Keys(), aRows, aHeader
    ' Output daily astronomy transposed data to table
    With Sheets(5)
        .Cells.Delete
        Output2DArray .Cells(1, 1), WorksheetFunction.Transpose(aHeader)
        Output2DArray .Cells(1, 2), WorksheetFunction.Transpose(aRows)
        .Columns.AutoFit
    End With
    ' Convert hourly history data to arrays
    JSON.ToArray vJSON("history")("days")(0)("hours"), aRows, aHeader
    ' Output hourly history data to table
    With Sheets(6)
        .Cells.Delete
        OutputArray .Cells(1, 1), aHeader
        Output2DArray .Cells(2, 1), aRows
        .Columns.AutoFit
    End With
    MsgBox "Completed"

End Sub

Sub OutputArray(oDstRng As Range, aCells As Variant)

    With oDstRng
        .Parent.Select
        With .Resize( _
                1, _
                UBound(aCells) - LBound(aCells) + 1)
            .NumberFormat = "@"
            .Value = aCells
        End With
    End With

End Sub

Sub Output2DArray(oDstRng As Range, aCells As Variant)

    With oDstRng
        .Parent.Select
        With .Resize( _
                UBound(aCells, 1) - LBound(aCells, 1) + 1, _
                UBound(aCells, 2) - LBound(aCells, 2) + 1)
            .NumberFormat = "@"
            .Value = aCells
        End With
    End With

End Sub

第二个XHR返回JSON数据,以清楚说明如何从其中提取必要的数据,您可以将JSON保存到文件中,复制内容并将其粘贴到任何JSON查看器中以进行进一步研究。我使用在线工具
http://jsonviewer.stack.hu,

有6个主要部分,提取了数据的相关部分并将其输出到6个工作表(必须在运行之前手动创建):

Sheet1 - Daily forecast
Sheet2 - Horly forecast
Sheet3 - Response data (transposed)
Sheet4 - Current data (transposed)
Sheet5 - Astronomy (transposed)
Sheet6 - Hourly history data

有了该示例,您可以从该JSON响应中提取所需的数据。



 类似资料:
  • 问题内容: 我花了一天的时间研究可用于完成以下任务的图书馆: 检索网页的全部内容(例如在后台),而不向视图渲染结果。 例如,lib应该支持触发ajax请求的页面,以便在加载初始HTML之后加载一些其他结果数据。 从生成的html中,我需要获取xpath或CSS选择器形式的元素。 将来我可能还需要导航到下一页(触发事件,提交按钮/链接等) 这是我尝试未成功的尝试: Jsoup:效果很好,但不支持ja

  • 问题内容: 我试图从HTML中提取许多页面的数据(数字)。每个页面的数据都不同。当我尝试使用soup.select(’span [class =“ pull- right”]’)时,它应该给我编号,但只有标签出现。我相信这是因为网页中使用了Javascript。180,476是我要在许多页面上使用的特定HTML处的数据位置: 我的代码(这在很多页面上都是循环的): 输出: 范例网址:https:/

  • 问题内容: 我想编写一个vba程序,该程序可以从网页自动下载历史库存数据。选择数据并单击下载按钮已在起作用。但是我也想更改日期,不适用于我的代码。 我想更改日期的Element的相应HTML代码,您可以在以下链接下找到该日期: 我要更改日期的元素的HTML代码 我现在使用的代码如下: 我非常感谢您的帮助! 问题答案: 请尝试以下方法。实际上,它单击年份和月份的下拉菜单,然后通过属性值选择适当的项目

  • 问题内容: 我想从网站上获取每天的日出/日落时间。是否可以使用Python抓取网络内容?使用什么模块?有没有可用的教程? 问题答案: 结合使用urllib2和出色的BeautifulSoup库:

  • 网页爬取 编写网页需要使用 HTML 语言,如果你有 HTML 学习经历就能知道所谓 HTML 语言就是一种规格化文档。有时我们能很方便的从中获取一些需要的数据,并且保持数据原有格式,如 csv 、json 等格式。但有时网站并不会提供一目了然的数据格式。 所以我们就需要爬取网页。网页爬取就是通过电脑程序编写,从不同的网页中去删选、挖掘你需要的数据,并且保存数据相应的格式。 网页请求( Reque

  • 本文向大家介绍JavaScript对HTML DOM使用EventListener进行操作,包括了JavaScript对HTML DOM使用EventListener进行操作的使用技巧和注意事项,需要的朋友参考一下 addEventListener() 方法 实例 点用户点击按钮时触发监听事件: addEventListener() 方法用于向指定元素添加事件句柄。 addEventListene