【问题标题】:Using XMLHTTP in Excel VBA to download website's table not working在 Excel VBA 中使用 XMLHTTP 下载网站的表格不起作用
【发布时间】:2021-11-25 22:45:28
【问题描述】:

我正在尝试从以下网站下载历史黄金价格表: www.lbma.org.uk/prices-and-data/precious-metal-prices#/table

Dim http As MSXML2.XMLHTTP60 
Set http = New MSXML2.XMLHTTP60

With http
     .Open "GET", "https://www.lbma.org.uk/prices-and-data/precious-metal-prices#/table", True 
     .setRequestHeader "User-Agent", "Mozilla/5.0"
     .setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
     .send

     Do  ' Wait till the page is loaded
        DoEvents
        Sleep (1)
    Loop Until .ReadyState = 4
End With

http.responseText 长 115kB,包含页面中的所有文本等,但没有包含黄金价格数据的实际表格。我对 xmlhttp 很陌生 - 知道我做错了什么吗?

【问题讨论】:

  • 您使用的方法适用于您想要的内容包含在页面源中的页面:在提供页面后在浏览器中创建内容的页面通常需要不同的方法。您可以尝试自动化 IE 或查看 Selenium Basic。
  • 我还看到可以通过将某些标头编码为 URL 格式来生成“导出到 xlsx”地址。这将让您中途自动将最近的数据下载到 xlsx 文件中,然后您可以使用 VBA 打开和复制数据。这是解码后的 URL:https://prices.lbma.org.uk/export/xls/?c={"metals":["gold"],"type":"daily","currency":["usd","gbp","eur"],"published":["am","pm"],"dates":{"start":"2021-01-01","end":"2021-10-05"}}
  • 谢谢,我试图避免使用 IE11,因为我发现它在 VBA 中完全没有希望,而且它几乎已经过时了。关于 URL(设计得很好!),但我需要它完全自动化并且看不到如何让 Excel “按保存”。我想我可以使用 AutoIt,但它有点啰嗦(= 不可靠)
  • @drb01 您希望能够选择下载数据的日期吗?如果是,那么 URL 方法似乎就是这样做的方法。至于“按保存”,您甚至都不需要。 VBA 会在后台下载 excel 文件,复制感兴趣的数据,关闭下载的 excel 文件并将数据粘贴到 您的 excel 文件中。如果您不关心选择日期,那么网站会返回一个 huge JSON 响应,其中包含从 1968 年到今天的所有数据。当然,一旦下载,您仍然可以获得所需的日期,但这需要一段时间......

标签: excel vba xmlhttprequest


【解决方案1】:

这是一种仅拉动 AM 价格的方法,如果您愿意,这应该很容易扩展到拉 PM 价格。

我所做的是查看在此站点上发出的XHR 请求,并注意到它使用 JSON 将数据发送到页面以获取每个部分的价格。这可能是您在页面上找不到表格 HTML 的原因,它正在创建中。

为了获得此代码,您需要加载 VBA-JSON 项目。这是用来解析JSON的,你可以找到here。按照该页面上的说明进行添加

代码

Option Explicit

Public Function GetHistoricalGoldPricesJSON() As String
    On Error GoTo ErrHand:
    Const url As String = "https://prices.lbma.org.uk/json/gold_am.json?r=166366104"
    
    With CreateObject("MSXML2.XMLHTTP")
         .Open "GET", url, False
         .send
         GetHistoricalGoldPricesJSON = .ResponseText
    End With
    
    Exit Function
    
ErrHand:
    GetHistoricalGoldPricesJSON = ""
End Function

Public Function GetGoldPricesJSON(JsonString As String) As Object
    On Error Resume Next
    If JsonString = "" Then
        Set GetGoldPricesJSON= Nothing
        Exit Function
    End If
    
    Set GetGoldPricesJSON= JsonConverter.ParseJson(JsonString)
End Function

Public Sub GetGoldPrices()
    Dim GoldPrices As Object: Set GoldPrices = GetGoldPricesJSON(GetHistoricalGoldPricesJSON())
    
    'Nothing found or there was an error
    If GoldPrices Is Nothing Then Exit Sub
    
    Dim GoldPrice  As Variant
    Dim GoldArray  As Variant
    Dim Price      As Variant: ReDim GoldArray(1 To 50000, 1 To 4)
    Dim i          As Long
    
    For Each GoldPrice In GoldPrices
        i = i + 1
        GoldArray(i, 1) = GoldPrice("d")
        GoldArray(i, 2) = GoldPrice("v")(1)
        GoldArray(i, 3) = GoldPrice("v")(2)
        GoldArray(i, 4) = GoldPrice("v")(3)
    Next
    
    With ThisWorkbook.Sheets(1)
        .Cells.ClearContents
        .Range("A1:D1") = Array("Date", "USD AM Price", "GBP AM Price", "EUR AM Price")
        .Range(.Cells(2, 1), .Cells(i + 1, 4)) = GoldArray
    End With
    
End Sub

【讨论】:

  • 太不可思议了!但是出于兴趣,以防将来发生变化,您如何计算出URL“prices.lbma.org.uk/json/gold_am.json?r=166366104
  • @drb01 我查看了网络流量并弄清楚了页面是如何工作的。您可以在开发工具中(通常在“网络”选项卡上)查看服务器和浏览器正在交换的 Web 请求。
  • 知道了。知道 ?r=166366104 是做什么的吗?如果我将其更改为 ?r=1 似乎没有太大区别。
  • 不完全确定,可以用于追踪。
猜你喜欢
  • 1970-01-01
  • 2013-07-23
  • 2018-02-25
  • 1970-01-01
  • 2013-09-14
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多